我在WPF应用程序中有一个DataGrid
,它为我的ItemsSource
编写了一个自定义集合。该集合强制其所有项目满足特定要求(即它们必须介于某些最小值和最大值之间)。
集合的类签名是:
public class CheckedObservableCollection<T> : IList<T>, ICollection<T>, IList, ICollection,
INotifyCollectionChanged
where T : IComparable<T>, IEditableObject, ICloneable, INotifyPropertyChanged
我希望能够使用DataGrid
功能,在DataGrid
的最后一行提交修改会导致新项目添加到ItemsSource
的末尾。
不幸的是DataGrid
只是添加了一个使用默认构造函数创建的新项目。因此,在添加新项目时,DataGrid
间接(通过其ItemCollection
密封类)声明:
ItemsSource.Add(new T())
其中T是CheckedObservableCollection中元素的类型。我想为网格添加一个不同的T,一个满足强加于集合的约束。
我的问题是:有没有内置的方法来做到这一点?有人这样做了吗?什么是最好的(最简单,最快的代码;性能不是问题)这样做的方法?
目前我只是派生DataGrid
来覆盖我自己的OnExecutedBeginEdit
函数,如下所示:
public class CheckedDataGrid<T> : DataGrid where T : IEditableObject, IComparable<T>, INotifyPropertyChanged, ICloneable
{
public CheckedDataGrid() : base() { }
private IEditableCollectionView EditableItems {
get { return (IEditableCollectionView)Items; }
}
protected override void OnExecutedBeginEdit(ExecutedRoutedEventArgs e) {
try {
base.OnExecutedBeginEdit(e);
} catch (ArgumentException) {
var source = ItemsSource as CheckedObservableCollection<T>;
source.Add((T)source.MinValue.Clone());
this.Focus();
}
}
}
其中MinValue
是集合中允许的最小项目。
我不喜欢这个解决方案。如果你们有任何建议我会非常感激!
由于
答案 0 :(得分:3)
此问题现在使用4.5
的{{1}}事件在AddingNewItem
下可以半解决。 Here is my answer to a similar question
我使用DataGrid的
DataGrid
事件解决了这个问题。这几乎entirely undocumented event不仅会告诉您正在添加新项目,而且[允许您选择要添加的项目] [2]。AddingNewItem
先发火花;AddingNewItem
的{{1}}属性只是NewItem
。即使您为事件提供了处理程序,DataGrid也会拒绝允许用户添加 如果类没有默认构造函数,则为行。但是,奇怪的是(但幸运的是)如果你有一个,并设置
EventArgs
的{{1}}属性,它永远不会被调用。如果您选择这样做,您可以使用
null
和NewItem
等属性,以确保没有人调用构造函数。您也可以让构造函数体抛出异常反编译控件让我们看看那里发生了什么......
答案 1 :(得分:1)
对于任何感兴趣的人,我最后只使用BindingList<T>
而不是ObservableCollection<T>
来推导解决问题,将我的派生类用作常规ItemsSource
中的DataGrid
:
public class CheckedBindingList<T> : BindingList<T>, INotifyPropertyChanged where T : IEditableObject, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Predicate<T> _check;
private DefaultProvider<T> _defaultProvider;
public CheckedBindingList(Predicate<T> check, DefaultProvider<T> defaultProvider) {
if (check == null)
throw new ArgumentNullException("check cannot be null");
if (defaultProvider != null && !check(defaultProvider()))
throw new ArgumentException("defaultProvider does not pass the check");
_check = check;
_defaultProvider = defaultProvider;
}
/// <summary>
/// Predicate the check item in the list against.
/// All items in the list must satisfy Check(item) == true
/// </summary>
public Predicate<T> Check {
get { return _check; }
set {
if (value != _check) {
RaiseListChangedEvents = false;
int i = 0;
while (i < Items.Count)
if (!value(Items[i]))
++i;
else
RemoveAt(i);
RaiseListChangedEvents = true;
SetProperty(ref _check, value, "Check");
ResetBindings();
}
}
}
public DefaultProvider<T> DefaultProvider {
get { return _defaultProvider; }
set {
if (!_check(value()))
throw new ArgumentException("value does not pass the check");
}
}
protected override void OnAddingNew(AddingNewEventArgs e) {
if (e.NewObject != null)
if (!_check((T)e.NewObject)) {
if (_defaultProvider != null)
e.NewObject = _defaultProvider();
else
e.NewObject = default(T);
}
base.OnAddingNew(e);
}
protected override void OnListChanged(ListChangedEventArgs e) {
switch (e.ListChangedType) {
case (ListChangedType.ItemAdded):
if (!_check(Items[e.NewIndex])) {
RaiseListChangedEvents = false;
RemoveItem(e.NewIndex);
if (_defaultProvider != null)
InsertItem(e.NewIndex, _defaultProvider());
else
InsertItem(e.NewIndex, default(T));
RaiseListChangedEvents = true;
}
break;
case (ListChangedType.ItemChanged):
if (e.NewIndex >= 0 && e.NewIndex < Items.Count) {
if (!_check(Items[e.NewIndex])) {
Items[e.NewIndex].CancelEdit();
throw new ArgumentException("item did not pass the check");
}
}
break;
default:
break;
}
base.OnListChanged(e);
}
protected void SetProperty<K>(ref K field, K value, string name) {
if (!EqualityComparer<K>.Default.Equals(field, value)) {
field = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
此类不完整,但上面的实现足以验证静态类型(不是由反射或DLR构建)对象或值类型的列表。