在 UserControl 之间传递具有不同类型参数的泛型类

发布于 2024-10-06 21:31:03 字数 2053 浏览 0 评论 0原文

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

我有一个通用容器类 SelectableItems ,需要 T 符合这些约束: where T : ICheckable, IEquatable, IDeepCloneable. SelectableItems 提供 ObservableCollectionItems 属性,以及其他有用的属性,例如 bool IsAnyItemSelectedT SelectedItem 等。这些属性将用于实现“全选”等命令。 TemplateDefect 都符合所有这些约束。我打算在新用户控件中创建一个依赖属性,并将其他用户控件中的 SelectableItems

总而言之,这就是我想要的:

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 用户控件中,以获取 SelectableItemsSelectableItems中的所有有用属性。 T> 视图模型,例如 IsAnyItemSelected 等。这对于大多数属性来说都很好,但对于 ObservableCollection这样做我犹豫不决。 Items 因为我遇到了与上述相同的通用问题,并且如果我只使用 IEnumerable 而不是 ObservableCollection,我不相信事情会正常工作>。也许我应该创建一个非通用的 ObservableCollection 类(例如这个问题)?

I currently have a couple different user controls that provide the same functionality: three different buttons called Select All, Deselect All, and Toggle Selected. These perform actions on a list of items that implement my ICheckable interface in each user control. I wanted to unify this stuff so that the commands and buttons would all be defined in one place only--a new user control--instead of being duplicated in two different user controls. My problem is that in one user control I'm dealing with a list of my Template class, and the other user control has a list of a Defect class. Both Template and Defect implement ICheckable, meaning the Select All, Deselect All, and Toggle Selected apply to them.

I have a generic container class SelectableItems<T> that requires T fit these constraints: where T : ICheckable, IEquatable<T>, IDeepCloneable<T>. SelectableItems<T> provides an ObservableCollection<T> Items property, along with other useful properties such as bool IsAnyItemSelected, T SelectedItem, etc. These properties would be used in implementing the Select All, etc. commands. Both Template and Defect fit all those constraints. I was going to create a dependency property in my new user control to which I would bind a SelectableItems<Template> and SelectableItems<Defect> property from my other user controls. I don't think it's possible to do a generic dependency property, though, because I can't have a generic UserControl class since I'm using XAML. How should I go about this? I'm using .NET 3.5.

To sum up, this is what I want:

TemplateList user control                             ItemSelection user control
-------------------------------------------           --------------------------
SelectableItems<Template> TemplateContainer ==Bind==> unknownType? ItemContainer

DefectList user control                           ItemSelection user control
---------------------------------------           --------------------------
SelectableItems<Defect> DefectContainer ==Bind==> unknownType? ItemContainer

Edit: I considered just adding dependency properties to my new ItemSelection user control for all the useful properties in the SelectableItems<T> view model, such as IsAnyItemSelected, etc. That would be fine for most of the properties, but I was hesitant to do it for ObservableCollection<T> Items because I hit the same generic problem as described above, and I didn't trust things to work okay if I just used IEnumerable instead of ObservableCollection<something>. Maybe I should make an ObservableCollection class that isn't generic (like in this question)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

堇色安年 2024-10-13 21:31:03

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

Creating a non-generic ObservableCollection class and then using a value converter to convert my ObservableCollection<T> value to an ObservableCollection seems to have worked.

Here are the important parts of my ObservableCollection class:

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

And here's the value converter:

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

And I bind like so:

<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}"/>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文