我目前有几个不同的用户控件提供相同的功能:三个不同的按钮,名为Select All,Deselect All和Toggle Selected。这些操作对在每个用户控件中实现我的ICheckable
接口的项列表执行操作。我想统一这些东西,以便命令和按钮都只在一个地方定义 - 一个新的用户控件 - 而不是在两个不同的用户控件中复制。我的问题是,在一个用户控件中,我正在处理我的Template
类的列表,而另一个用户控件有一个Defect
类的列表。 Template
和Defect
都会实现ICheckable
,这意味着全部选择,取消全选和切换选择都适用于它们。
我有一个通用容器类SelectableItems<T>
,需要T
符合这些约束:where T : ICheckable, IEquatable<T>, IDeepCloneable<T>
。 SelectableItems<T>
提供了ObservableCollection<T> Items
属性以及其他有用的属性,例如bool IsAnyItemSelected
,T SelectedItem
等。这些属性将用于实现Select All等命令。 Template
和Defect
都适合所有这些约束。我打算在我的新用户控件中创建一个依赖项属性,我将从其他用户控件绑定SelectableItems<Template>
和SelectableItems<Defect>
属性。我认为不可能做一个通用依赖属性,因为我使用XAML时不能有一个通用的UserControl
类。我该怎么办呢?我正在使用.NET 3.5。
总结一下,这就是我想要的:
TemplateList user control ItemSelection user control
------------------------------------------- --------------------------
SelectableItems<Template> TemplateContainer ==Bind==> unknownType? ItemContainer
DefectList user control ItemSelection user control
--------------------------------------- --------------------------
SelectableItems<Defect> DefectContainer ==Bind==> unknownType? ItemContainer
修改:我考虑为ItemSelection
视图模型中的所有有用属性添加依赖项属性到我的新SelectableItems<T>
用户控件,例如IsAnyItemSelected
对于大多数属性来说都没问题,但是对于ObservableCollection<T> Items
我做的很犹豫,因为我遇到了如上所述的相同的通用问题,如果我只是我不相信事情可以正常工作使用IEnumerable
代替ObservableCollection<something>
。也许我应该创建一个非通用的ObservableCollection
类(比如在this question中)?
答案 0 :(得分:0)
创建非通用ObservableCollection
类,然后使用值转换器将ObservableCollection<T>
值转换为ObservableCollection
似乎已经有效。
以下是我ObservableCollection
课程的重要部分:
public class ObservableCollection : ICollection<object>,
INotifyCollectionChanged
{
private ObservableCollection<object> _collection;
public ObservableCollection()
{
_collection = new ObservableCollection<object>();
_collection.CollectionChanged +=
new NotifyCollectionChangedEventHandler(collectionChanged);
}
public ObservableCollection(IEnumerable items)
{
if (null == items)
{
throw new ArgumentNullException("items");
}
_collection = new ObservableCollection<object>();
foreach (object item in items)
{
Add(item);
}
_collection.CollectionChanged +=
new NotifyCollectionChangedEventHandler(collectionChanged);
}
...stuff necessary to implement ICollection<object>...
public event NotifyCollectionChangedEventHandler CollectionChanged;
void collectionChanged(object sender,
NotifyCollectionChangedEventArgs e)
{
NotifyCollectionChangedEventHandler handler = CollectionChanged;
if (null != handler)
{
handler(this, e);
}
}
}
这是价值转换器:
public class EnumerableToObservableCollectionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
if (targetType != typeof(ObservableCollection))
{
throw new ArgumentException("Do not use this converter except " +
"when going to ObservableCollection");
}
var enumerable = value as IEnumerable;
if (null == enumerable)
{
return new ObservableCollection();
}
return new ObservableCollection(enumerable);
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return value;
}
}
我这样绑定:
<local:ItemSelection SelectedItems="{Binding Path=MyViewModel.SelectedItems,
Mode=OneWay}"
Items="{Binding Path=MyViewModel.Items, Mode=OneWay,
Converter={StaticResource observCollConverter}}"
IsAnyItemSelected="{Binding Path=MyViewModel.IsAnyItemSelected,
Mode=OneWay}"/>