C# 在UserControls之间传递具有不同类型参数的泛型类

C# 在UserControls之间传递具有不同类型参数的泛型类,c#,wpf,generics,user-controls,covariance,C#,Wpf,Generics,User Controls,Covariance,我目前有两个不同的用户控件,它们提供相同的功能:三个不同的按钮,分别称为全选、全选和切换选择。它们对在每个用户控件中实现我的ICheckable界面的项目列表执行操作。我想统一这些东西,这样命令和按钮都只能在一个地方定义——一个新的用户控件,而不是在两个不同的用户控件中重复。我的问题是,在一个用户控件中,我处理的是模板类的列表,而另一个用户控件中有缺陷类的列表。模板和缺陷都实现了ICheckable,这意味着选择全部、取消选择全部和切换选择应用于它们 我有一个通用容器类SelectableIte

我目前有两个不同的用户控件,它们提供相同的功能:三个不同的按钮,分别称为全选、全选和切换选择。它们对在每个用户控件中实现我的ICheckable界面的项目列表执行操作。我想统一这些东西,这样命令和按钮都只能在一个地方定义——一个新的用户控件,而不是在两个不同的用户控件中重复。我的问题是,在一个用户控件中,我处理的是模板类的列表,而另一个用户控件中有缺陷类的列表。模板和缺陷都实现了ICheckable,这意味着选择全部、取消选择全部和切换选择应用于它们

我有一个通用容器类SelectableItems,它需要满足以下约束:其中T:ICheckable、IEquatable、IDeepCloneable。SelectableItems提供了ObservableCollection Items属性,以及其他有用的属性,如bool IsAnyItemSelected、T SelectedItem等。这些属性将用于实现全选等命令。模板和缺陷都符合所有这些约束。我打算在我的新用户控件中创建一个依赖项属性,并将其他用户控件中的SelectableItems和SelectableItems属性绑定到该属性。不过,我认为不可能使用泛型依赖属性,因为我使用XAML时无法使用泛型UserControl类。我该怎么做?我正在使用.NET3.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
编辑:我考虑只为SelectableItems视图模型中的所有有用属性(如IsAnyItemSelected等)向我的新ItemSelection用户控件添加依赖项属性。这对大多数属性都很好,但是对于ObservableCollection项,我很犹豫是否要这样做,因为我遇到了如上所述的一般问题,并且我不相信如果我只是使用IEnumerable而不是ObservableCollection,事情会正常工作。也许我应该创建一个非泛型的ObservableCollection类,就像创建一个非泛型的ObservableCollection类,然后使用值转换器将ObservableCollection值转换为ObservableCollection似乎已经奏效了

以下是我的ObservableCollection课程的重要部分:

我是这样捆绑的:

<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}"/>

我突然想到我可能不需要写一个非通用的ObservableCollection,我可以用一个转换器将ObservableCollection转换成ObservableCollection。。。好吧。
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}"/>