WPF DataGrid CanUserAddRows = True

It seems I have a problem with adding rows to a DataGrid via the interface itself. Here is a screenshot of the user interface:

Screenshot

As you can see, 0 rows were found in the database, so nothing is displayed on the right side of the DataGrid . But id, as if there is one empty line, for manually adding lines. DataGrid.CanUserAddRows set to True , but it does not work. Here is the xaml for the DataGrid , I took the liberty of removing part of the code to make it smaller.

PrivilegeDetailsView.xaml

 <UserControl ... d:DataContext="{d:DesignInstance impl:PrivilegeDetailsViewModel}"> <DataGrid ... ItemsSource="{Binding RolesHasPrivilegesOnObjects}" AutoGenerateColumns="False" CanUserAddRows="True"> <DataGrid.Columns> <DataGridTemplateColumn Header="Type" CanUserSort="True"> <DataGridTemplateColumn.CellTemplate> <DataTemplate DataType="{x:Type int:IRoleHasPrivilegeOnObjectListItemViewModel}"> <Image Source="{Binding Icon}" ToolTip="{Binding ToolTip}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTextColumn Width="*" Header="Name" Binding="{Binding Name}"/> <DataGridCheckBoxColumn Header="Select" Binding="{Binding HasSelect, UpdateSourceTrigger=PropertyChanged}"> <DataGridCheckBoxColumn.ElementStyle> <Style TargetType="CheckBox"> <Style.Triggers> <DataTrigger Binding="{Binding CanHaveSelect}" Value="True"> <Setter Property="IsEnabled" Value="True"/> <Setter Property="HorizontalAlignment" Value="Center"/> </DataTrigger> <DataTrigger Binding="{Binding CanHaveSelect}" Value="False"> <Setter Property="IsEnabled" Value="False"/> <Setter Property="HorizontalAlignment" Value="Center"/> </DataTrigger> </Style.Triggers> </Style> </DataGridCheckBoxColumn.ElementStyle> </DataGridCheckBoxColumn> ... </DataGrid.Columns> </DataGrid> </UserControl> 

PrivilegeDetailsView.xaml.cs

 public partial class PrivilegeDetailsView : IPrivilegeDetailsView { public PrivilegeDetailsView() { InitializeComponent(); } public DataGrid PrivilegesOnObjectsDataGrid { get { return PrivilegeDataGrid; } } public IViewModel ViewModel { get { return (IViewModel)DataContext; } set { DataContext = value; } } } 

Here is the ViewModel (VM) for xaml View above:

PrivilegeDetailsViewModel.cs

 public class PrivilegeDetailsViewModel : ViewModelBase, IPrivilegeDetailsViewModel { private readonly IEventAggregator _eventAggregator; private readonly IPrivilegeViewModel _privilegeViewModel; private readonly IRoleHasPrivilegeOnObjectViewModelAdapterRepository _roleHasPrivilegeOnObjectViewModelAdapterRepository; private ObservableCollection<IRoleHasPrivilegeOnObjectListItemViewModel> _rolesHasPrivilegesOnObjects; public PrivilegeDetailsViewModel(IPrivilegeDetailsView view, IRoleHasPrivilegeOnObjectViewModelAdapterRepository roleHasPrivilegeOnObjectViewModelAdapterRepository, IPrivilegeViewModel privilegeViewModel, IEventAggregator eventAggregator) : base(view) { _roleHasPrivilegeOnObjectViewModelAdapterRepository = roleHasPrivilegeOnObjectViewModelAdapterRepository; _privilegeViewModel = privilegeViewModel; _eventAggregator = eventAggregator; Initialize(); } protected override sealed void Initialize() { _privilegeViewModel.PropertyChanged += PrivilegeViewModelOnPropertyChanged; _eventAggregator.GetEvent<ToggleSelectPrivilegeEvent>().Subscribe(ToggleSelectPrivilege); ... } public new IPrivilegeDetailsView View { get { return (IPrivilegeDetailsView)base.View; } } public ObservableCollection<IRoleHasPrivilegeOnObjectListItemViewModel> RolesHasPrivilegesOnObjects { get { return _rolesHasPrivilegesOnObjects; } set { _rolesHasPrivilegesOnObjects = value; OnPropertyChanged(); } } public void Save() { if(RolesHasPrivilegesOnObjects == null) return; _roleHasPrivilegeOnObjectViewModelAdapterRepository.SaveChanges(RolesHasPrivilegesOnObjects); } private void ToggleExecutePrivilege(object obj) { var toggle = !View.PrivilegesOnObjectsDataGrid.SelectedItems.Cast<IRoleHasPrivilegeOnObjectListItemViewModel>() .All(x => x.HasExecute); foreach(var selectedItem in View.PrivilegesOnObjectsDataGrid .SelectedItems .Cast<IRoleHasPrivilegeOnObjectListItemViewModel>() .Where(selectedItem => selectedItem.Object .CanHavePrivilege("EXECUTE"))) { selectedItem.HasExecute = toggle; } } ... private void PrivilegeViewModelOnPropertyChanged(object s, PropertyChangedEventArgs e) { switch(e.PropertyName) { //When the SelectedSchema changes in the parent VM, I get the new rows to be shown in the DataGrid. case "SelectedSchema": RolesHasPrivilegesOnObjects = _roleHasPrivilegeOnObjectViewModelAdapterRepository .GetPrivilegesOnObjectsAssociatedWith((IRoleEntityViewModel)_privilegeViewModel.SelectedRole, (IContainerEntityViewModel)_privilegeViewModel.SelectedSchema); break; } } } 

This is the VM for each row in the DataGrid

RoleHasPrivilegeOnObjectEntityViewModel.cs

 public class RoleHasPrivilegeOnObjectEntityViewModel : EntityViewModelBase<RoleHasPrivilegeOnObjectEntityViewModel, RoleHasPrivilegesOnObject>, IRoleHasPrivilegeOnObjectListItemViewModel { private readonly RoleHasPrivilegesOnObject _roleHasPrivilegesOnObject; public RoleHasPrivilegeOnObjectEntityViewModel(RoleHasPrivilegesOnObject roleHasPrivilegesOnObject) { _roleHasPrivilegesOnObject = roleHasPrivilegesOnObject; Role = new RoleEntityViewModel(_roleHasPrivilegesOnObject.Role); Object = new ObjectEntityViewModel(_roleHasPrivilegesOnObject.Object); } public override EntityType EntityType { get { return EntityType.NONE; } } public override RoleHasPrivilegesOnObject OriginalEntity { get { return _roleHasPrivilegesOnObject; } } public IRoleEntityViewModel Role { get; set; } public IObjectEntityViewModel Object { get; set; } public string ToolTip { get { return _roleHasPrivilegesOnObject.ToolTip; } } public bool HasExecute { get { return _roleHasPrivilegesOnObject.HasExecute; } set { _roleHasPrivilegesOnObject.HasExecute = value; OnPropertyChanged(); } } public bool CanHaveExecute { get { return _roleHasPrivilegesOnObject.CanHaveExecute; } } public override string Icon { get { return Object != null ? Object.Icon : string.Empty; } } public override string NAME { get { return _roleHasPrivilegesOnObject.NAME; } set { _roleHasPrivilegesOnObject.NAME = value; OnPropertyChanged(); } } ... } 

I know that this is a lot of code, I removed a lot and put a few dots (...) to show that there is more code. NOTE. Im using EF5 and PRISM

How to force DataGrid to accept new lines through the graphical interface?

+6
source share
2 answers

What I finished was partly / Basically what Maverick suggested.

I changed the ObservableCollection<IRoleHasPrivilegeOnObjectListItemViewModel> to ObservableCollection<RoleHasPrivilegeOnObjectEntityViewModel> and created a default constructor that it did not previously have.

The problem was that RoleHasPrivilegeOnObjectEntityViewModel needed some fields and properties set to work, so I created a public Initialize function to provide the necessary parameters.

I added an event handler to the DataGrid's InitializingNewItem event, where I named the Initialize function.

 private void PrivilegesOnObjectsDataGridOnInitializingNewItem(object s, InitializingNewItemEventArgs e) { var newItem = e.NewItem as RoleHasPrivilegeOnObjectEntityViewModel; if (newItem == null) return; var role = _privilegeViewModel.SelectedRole; var schema = _privilegeViewModel.SelectedSchema; newItem.Initialize(role.OriginalEntity, schema.OriginalEntity); } 

When trying to add a new line, pressing ComboBox did not work InitializeNewItem event . But clicking any other column exited the InitializeNewItem event , and since each Row's VM initially had its own AvailableObjectTypes property, the ComboBox ItemSource not set if the ComboBox was selected before any other column, which makes it empty.

This was not acceptable behavior, so moving AvailableObjectTypes to PrivilegeDetailsViewModel and changing ComboBox's ItemSource to this helped

 ItemsSource="{Binding DataContext.AvailableObjectTypes, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" 
+5
source

I believe your problem is using ObservableCollection<IRoleHasPrivilegeOnObjectListItemViewModel> as ItemsSource . For a DataGrid to create a new row, there must be a type that can be created using an empty constructor.

If you changed it to say ObservableCollection<RoleHasPrivilegeOnObjectEntityViewModel> instead, I'm sure your rows will start to be added.

+12
source

All Articles