【问题标题】:How to Add a New Row to DataGrid in MVVM Friendly Way如何以 MVVM 友好的方式向 DataGrid 添加新行
【发布时间】:2013-12-10 08:10:29
【问题描述】:

我有以下DataGrid

<DataGrid CanUserDeleteRows="True" 
          CanUserAddRows="True"
          SelectedItem="{Binding SelectedResource, Mode=TwoWay}"
          ItemsSource="{Binding Path=Resources, Mode=TwoWay,
                                UpdateSourceTrigger=PropertyChanged, 
                                IsAsync=True}"> ... </<DataGrid>

我正在使用 MVVM 模式绑定到 ObservableCollection&lt;ResourceViewModel&gt; Resources,这很好用。我有一个添加新行的按钮,这是通过将新的 ResourceViewModel 添加到 Resources 集合来完成的 - 很棒。现在,我希望用户能够点击空的最后一行,这会自动在 DataGrid 中创建一条新记录。

我已经确定DataGridCanUserAddRows=True。我已确保我绑定到的集合 Resources (ResourceViewModel) 中的类具有默认构造函数(无参数),并且我已确保集合类型不是只读的。当用户单击最后一行时,默认构造函数会触发,但要正确实例化新的 ResourceViewModel 对象,需要引用 Resources 集合的网格...

我想我可以在CellBeginEdit 事件上使用和AttachedCommand,然后将一个新的ResourceViewModel 添加到那里的可观察集合中,有这样做的标准方法吗? p>


注意,我已经阅读了以下问题,这些问题对我没有帮助

  1. WPF DataGrid - Event for New Rows?
  2. How to add rows with a DataGrid and MVVM

编辑。事实证明,由于 WPF DataGrid 中的错误,我在执行此操作时遇到了问题。见Nigel Spencer's Blog。但是,他的修复目前对我不起作用...

【问题讨论】:

标签: c# wpf mvvm datagrid


【解决方案1】:

据我了解,您知道如何正确地将新项目添加到数据绑定集合中,从而将新项目添加到 DataGrid 中,而您的问题实际上与用户单击时如何执行此操作有关在DataGrid 的最后一行。在视图模型中处理某些事件的一般方法是创建一个为您处理该事件的Attached Property(如果尚不存在)。

例如,您可以创建一个Attached Property,将一个处理程序附加到相关事件和另一个ICommand 类型,您可以在调用事件处理程序时执行它。然后,您可以在视图模型中编写 ICommand 的功能(在其中向数据绑定集合添加新项目)并将您的 ICommand 实现数据绑定到 Attached ICommand Property

我很确定你知道如何定义Attached Propertys,所以我不会通过展示你来侮辱你。如果我误解了你,或者没有说清楚,请告诉我。

【讨论】:

  • 感谢您的回复。问题是我设置了一个附加命令来触发InitializingNewItem 事件。当我将DataGrid 的最后一行置于编辑模式并且在网格尝试创建新项目之前触发此事件。在这里我可以添加新项目,但DataGrid 继续尝试使用默认构造函数实例化项目本身。我无法阻止网格自动执行此操作,因为我可以使用命令和事件来做我想做的事......
  • 所以我想问题变成了,最好的方法是什么? A. 添加新行后取消事件(如何,我不知道)。 B. 让网格自己做这件事 - 但是如何在默认 ctor 中正确初始化对象?有这样做的标准方法吗?
  • 我很少使用这些控件,所以很遗憾,我无法提供有关它们的高级建议。祝你好运。
【解决方案2】:

这是一个附加属性,它注册了一个添加行的命令(假设源集合包含一个泛型类型参数):

public static readonly DependencyProperty RegisterAddCommandProperty = DependencyProperty.RegisterAttached("RegisterAddCommand", typeof(bool), typeof(DataGridExtensions), new PropertyMetadata(false, OnRegisterAddCommandChanged));
public static bool GetRegisterAddCommand(DependencyObject obj)
{
    return (bool)obj.GetValue(RegisterAddCommandProperty);
}
public static void SetRegisterAddCommand(DependencyObject obj, bool value)
{
    obj.SetValue(RegisterAddCommandProperty, value);
}
static void OnRegisterAddCommandChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if (sender is DataGrid)
    {
        var DataGrid = sender as DataGrid;
        if ((bool)e.NewValue)
            DataGrid.CommandBindings.Add(new CommandBinding(AddCommand, AddCommand_Executed, AddCommand_CanExecute));
    }
}

public static readonly RoutedUICommand AddCommand = new RoutedUICommand("AddCommand", "AddCommand", typeof(DataGridExtensions));
static void AddCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
    var DataGrid = sender as DataGrid;

    var ItemsSourceType = DataGrid.ItemsSource.GetType();
    var ItemType = ItemsSourceType.GetGenericArguments().Single();

    DataGrid.Items.Add(Activator.CreateInstance(ItemType));
}
static void AddCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = (sender as DataGrid).CanUserAddRows;
}

然后您可以将命令应用到按钮上,如下所示:

<Button Command="{x:Static Extensions:DataGridExtensions.AddCommand}"/>

别忘了指定命令目标。

【讨论】:

    猜你喜欢
    • 2011-06-10
    • 1970-01-01
    • 2014-07-03
    • 2012-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2013-03-31
    相关资源
    最近更新 更多