DataGrid - 更改编辑行为

时间:2010-07-09 22:23:22

标签: c# wpf mvvm datagrid

我有一个带有某种复杂行为的ChildViewModels的ObservableCollection。

当我去编辑一行时--DataGrid进入'编辑模式' - 这有效地禁用了当前单元格之外的UI通知,直到提交了行 - 这是预期的行为,更重要的是它可以被更改吗? / p>

示例:

public class ViewModel
{
    public ViewModel()
    {
        Childs = new ObservableCollection<ChildViewModel> {new ChildViewModel()};
    }
    public ObservableCollection<ChildViewModel> Childs { get; private set; }
}
public class ChildViewModel : INotifyPropertyChanged
{
    private string _firstProperty;
    public string FirstProperty
    {
        get { return _firstProperty; }
        set
        {
            _firstProperty = value;
            _secondProperty = value;
            OnPropetyChanged("FirstProperty");
            OnPropetyChanged("SecondProperty");
        }
    }

    private string _secondProperty;
    public string SecondProperty
    {
        get { return _secondProperty; }
        set
        {
            _secondProperty = value;
            OnPropetyChanged("SecondProperty");
        }
    }

    private void OnPropetyChanged(string property)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

在视图中:

<Window.Resources>
    <local:ViewModel x:Key="Data"/>
</Window.Resources>
<DataGrid DataContext="{Binding Source={StaticResource Data}}" ItemsSource="{Binding Childs}"/>

注意在离开行之前,第一列编辑时的第二个通知是如何隐藏的。

编辑:实现IEditableObject不执行任何操作:

public class ChildViewModel : INotifyPropertyChanged,IEditableObject
{
    ...
    private ChildViewModel _localCopy;

    public void BeginEdit()
    {
        _localCopy = new ChildViewModel {FirstProperty = FirstProperty, SecondProperty = SecondProperty};
    }

    public void EndEdit()
    {
        _localCopy = null;
    }

    public void CancelEdit()
    {
        SecondProperty = _localCopy.SecondProperty;
        FirstProperty = _localCopy.FirstProperty;
    }
}

3 个答案:

答案 0 :(得分:7)

使用BindingGroup在DataGrid中实现此行为。 DataGrid设置ItemsControl.ItemBindingGroup以便将BindingGroup应用于每一行。它会在MeasureOverride中初始化,因此您可以覆盖MeasureOverride并清除它们:

public class NoBindingGroupGrid
    : DataGrid
{
    protected override Size MeasureOverride(Size availableSize)
    {
        var desiredSize = base.MeasureOverride(availableSize);
        ClearBindingGroup();
        return desiredSize;
    }

    private void ClearBindingGroup()
    {
        // Clear ItemBindingGroup so it isn't applied to new rows
        ItemBindingGroup = null;
        // Clear BindingGroup on already created rows
        foreach (var item in Items)
        {
            var row = ItemContainerGenerator.ContainerFromItem(item) as FrameworkElement;
            row.BindingGroup = null;
        }
    }
}

答案 1 :(得分:4)

这是一个非常古老的问题,但是一个更好的解决方案并不需要子类化DataGrid。只需在CellEditEnding事件中调用CommitEdit():

bool manualCommit = false;

private void MyDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    if (!manualCommit)
    {
        manualCommit = true;
        MyDataGrid.CommitEdit(DataGridEditingUnit.Row, true);
        manualCommit = false;
    }
}

答案 2 :(得分:0)

好的,所以,这就是问题所在。 Observable Collection不会通知它包含的对象发生变化。它只在添加/删除/等时通知。更新集合的操作是自我。

我遇到了这个问题,不得不手动将我的列添加到datagrid,然后在Column对象上设置Binding项。所以它会绑定到我的内容。

此外,我使ICollectionView中的对象派生自IEditableObject,因此当它们“更新”时,网格将自行刷新。

这很糟糕,但它是我必须做的才能让它发挥作用。

可选地,您可以创建自己的ObservableCollection,在添加和删除项目时附加/分离属性更改的处理程序。