2010-07-09 66 views
1

我有一个具有复杂行为的ChildViewModels的ObservableCollection。DataGrid - 更改编辑行为

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

例子:

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

回答

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

令人惊叹!非常感谢你!这让我甩掉了一小撮头发:)我会尽快奖励赏金。 – Goblin 2010-07-13 14:04:15

0

行,所以,这里的问题。 Observable Collection不会通知它包含更改的对象。它只通知添加/删除/等。更新集合的操作是自己的。

我有这个问题,不得不手动添加我的列到数据网格,然后设置列对象的绑定项目。所以它会绑定到我的内容。

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

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

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

+0

是 - 但是集合中的孩子在实现INotifyPropertyChanged时会通知。哦 - 太快了 - 会尝试。 – Goblin 2010-07-09 22:35:31

+0

好的 - 增加了IEditable接口并没有做任何事情 - 注意到有问题的对象已经在集合中了 - 它是在编辑属性时通知其他属性在提交该行之前无法触发的属性。 – Goblin 2010-07-09 22:49:08

+0

我使用了IEditableObject bc我的集合是一个ICollectionView。如果你不改变你的收藏,你仍然必须将你的财产改变的事件附加到收藏中的物品。另外,我不知道自动gen'd列添加绑定或不。 – 2010-07-09 22:55:11

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

虽然这不是严格的MVVM我喜欢这个简单的方法。 – user2190035 2017-03-29 08:02:09

+1

@ user2190035 - 它符合MVVM。代码中没有对视图模型的操作。代码纯粹与视图相关,这是适当的。 – user3690202 2017-04-06 08:03:16