WPF DataGrid CanUserAddRows = True

 丿艹约锭So灬幸福老师 发布于 2023-02-03 12:31

我似乎有一个问题,DataGrid通过接口本身添加行.以下是UI的屏幕截图:

截图

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

PrivilegeDetailsView.xaml


    
        
            
                
                    
                        
                    
                
            
            
            
                
                    
                
            
            ...
        
    

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

下面是ViewModel (VM)xaml View上面:

PrivilegeDetailsViewModel.cs

public class PrivilegeDetailsViewModel : ViewModelBase, IPrivilegeDetailsViewModel
{
    private readonly IEventAggregator _eventAggregator;
    private readonly IPrivilegeViewModel _privilegeViewModel;
    private readonly IRoleHasPrivilegeOnObjectViewModelAdapterRepository _roleHasPrivilegeOnObjectViewModelAdapterRepository;
    private ObservableCollection _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().Subscribe(ToggleSelectPrivilege);
        ...
    }

    public new IPrivilegeDetailsView View
    {
        get { return (IPrivilegeDetailsView)base.View; }
    }

    public ObservableCollection 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()
                          .All(x => x.HasExecute);
        foreach(var selectedItem in View.PrivilegesOnObjectsDataGrid
                                        .SelectedItems
                                        .Cast()
                                        .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;
        }
    }
}

这是VM对于每一行DataGrid

RoleHasPrivilegeOnObjectEntityViewModel.cs

public class RoleHasPrivilegeOnObjectEntityViewModel : EntityViewModelBase, 
                                                       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();
        }
    }

    ...
}

我知道这是很多代码,我已经剥离了很多并放置了几个点(...)来表明存在更多的代码.注意:我使用EF5和PRISM

如何DataGrid通过GUI接受新行?

2 个回答
  • 我相信你的问题是使用ObservableCollection<IRoleHasPrivilegeOnObjectListItemViewModel>ItemsSource.为了DataGrid能够创建新行,必须有一个可以使用空构造函数构造的类型.

    如果您将其更改为ObservableCollection<RoleHasPrivilegeOnObjectEntityViewModel>相反,我很确定您的行将开始添加.

    2023-02-03 12:34 回答
  • 我最终做的是部分/大部分是Maverik所建议的.

    我改为ObservableCollection<IRoleHasPrivilegeOnObjectListItemViewModel>be 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在任何其他列之前选择了它,则不会设置,因此将其设置为空.

    这是不是一个可以接受的行为让人感动AvailableObjectTypesPrivilegeDetailsViewModel和不断变化的ComboBox's ItemSource,以这有助于绑定

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

    2023-02-03 12:36 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有