WPF DataGrid CanUserAddRows = True

时间:2014-01-13 06:37:54

标签: wpf

我似乎在通过界面本身向DataGrid添加行时遇到问题。 以下是UI的屏幕截图:

Screenshot

如您所见,数据库中找到0行,因此右侧的DataGrid中没有显示任何内容。 但是id就像那里有一个空行,用于手动添加行。 DataGrid.CanUserAddRows设置为True,但无效。 以下是xaml的{​​{1}},我冒昧地删除了一些代码以使其变小。

PrivilegeDetailsView.xaml

DataGrid

PrivilegeDetailsView.xaml.cs

<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>

以上是public partial class PrivilegeDetailsView : IPrivilegeDetailsView { public PrivilegeDetailsView() { InitializeComponent(); } public DataGrid PrivilegesOnObjectsDataGrid { get { return PrivilegeDataGrid; } } public IViewModel ViewModel { get { return (IViewModel)DataContext; } set { DataContext = value; } } } ViewModel (VM)的{​​{1}}:

PrivilegeDetailsViewModel.cs

xaml

这是View

中每一行的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; } } }

RoleHasPrivilegeOnObjectEntityViewModel.cs

VM

我知道这是很多代码,我已经删除了很多并放置了几个点(...)来表明存在更多代码。注意:我正在使用EF5PRISM

如何让DataGrid通过GUI接受新行?

2 个答案:

答案 0 :(得分:12)

我认为您的问题是使用ObservableCollection<IRoleHasPrivilegeOnObjectListItemViewModel>作为ItemsSource。为了使DataGrid能够创建新行,必须有一个可以使用空构造函数构造的类型。

如果您将其更改为ObservableCollection<RoleHasPrivilegeOnObjectEntityViewModel>,我非常确定您的行会开始添加。

答案 1 :(得分:5)

我最终做的部分/大部分是Maverik所建议的。

我将ObservableCollection<IRoleHasPrivilegeOnObjectListItemViewModel>更改为ObservableCollection<RoleHasPrivilegeOnObjectEntityViewModel>并创建了一个默认构造函数,它以前没有。

问题是RoleHasPrivilegeOnObjectEntityViewModel需要设置一些字段和属性才能运行,因此我创建了一个公共Initialize函数来提供必要的参数。

我在DataGrid's InitializingNewItem事件中添加了一个事件处理程序,我调用了Initialize函数。

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);
}

尝试添加新行时,点击ComboBox并未触发InitializeNewItem event。但是点击任意其他列会触发InitializeNewItem event,因为最初每个Row's VM都拥有自己的AvailableObjectTypes属性,ComboBox如果在任何其他列之前选择了ItemSource,则未设置ComboBox,从而使其为空。

这不是一种可接受的行为,因此将AvailableObjectTypes移至PrivilegeDetailsViewModel并将ComboBox's ItemSource绑定更改为此帮助

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