我似乎在通过界面本身向DataGrid
添加行时遇到问题。
以下是UI的屏幕截图:
如您所见,数据库中找到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
我知道这是很多代码,我已经删除了很多并放置了几个点(...)来表明存在更多代码。注意:我正在使用EF5和PRISM
如何让DataGrid
通过GUI接受新行?
答案 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}}}"