【问题标题】:passing generic class with different type parameters between UserControls在 UserControls 之间传递具有不同类型参数的泛型类
【发布时间】:2010-12-08 21:47:23
【问题描述】:

我目前有几个提供相同功能的不同用户控件:三个不同的按钮,称为全选、取消全选和切换选定。这些对在每个用户控件中实现我的ICheckable 接口的项目列表执行操作。我想统一这些东西,以便命令和按钮都只在一个地方定义——一个新的用户控件——而不是在两个不同的用户控件中重复。我的问题是,在一个用户控件中,我正在处理我的Template 类的列表,而另一个用户控件有一个Defect 类的列表。 TemplateDefect 都实现了 ICheckable,这意味着 Select All、Deselect All 和 Toggle Selected 都适用于它们。

我有一个通用容器类 SelectableItems<T>,它要求 T 符合这些约束:where T : ICheckable, IEquatable<T>, IDeepCloneable<T>SelectableItems<T> 提供了一个ObservableCollection<T> Items 属性,以及其他有用的属性,例如bool IsAnyItemSelectedT SelectedItem 等。这些属性将用于实现全选等命令。 TemplateDefect 都适合所有这些约束。我打算在我的新用户控件中创建一个依赖属性,我将从我的其他用户控件绑定一个SelectableItems<Template>SelectableItems<Defect> 属性。不过,我认为不可能做一个通用的依赖属性,因为我不能有一个通用的 UserControl 类,因为我使用的是 XAML。我该怎么办?我正在使用 .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&lt;T&gt; 视图模型中所有有用的属性,例如IsAnyItemSelected 等。那就是对于大多数属性来说都很好,但我对 ObservableCollection&lt;T&gt; Items 犹豫不决,因为我遇到了与上述相同的一般问题,如果我只使用 IEnumerable 而不是 @987654346,我不相信事情可以正常工作@。也许我应该创建一个非通用的ObservableCollection 类(如this question)?

【问题讨论】:

    标签: c# wpf generics user-controls covariance


    【解决方案1】:

    创建一个非泛型ObservableCollection 类,然后使用值转换器将我的ObservableCollection&lt;T&gt; 值转换为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}"/>
    

    【讨论】:

    • 我突然想到我可能不需要写一个非通用的ObservableCollection,我可以使用转换器将ObservableCollection&lt;Defect&gt;转换为ObservableCollection&lt;object&gt;...啊好吧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-07
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    • 2019-03-05
    • 1970-01-01
    • 2019-02-27
    相关资源
    最近更新 更多