передача универсального класса с различными параметрами типа между UserControls - PullRequest
0 голосов
/ 09 декабря 2010

В настоящее время у меня есть пара различных пользовательских элементов управления, которые обеспечивают одинаковую функциональность: три разные кнопки, называемые «Выбрать все», «Отменить выбор всех» и «Переключить выбранные». Они выполняют действия со списком элементов, которые реализуют мой интерфейс 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 и т. Д. Эти свойства будут использоваться при реализации команд Выбрать все и т. Д. И Template, и Defect соответствуют всем этим ограничениям. Я собирался создать свойство зависимости в моем новом пользовательском элементе управления, к которому я бы привязал свойство 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<T>, таких как IsAnyItemSelected и т. Д. Это было бы хорошо для большинства свойств, но я не решался сделать это для ObservableCollection<T> Items, потому что я столкнулся с той же общей проблемой, как описано выше, и я не верил, что все работает нормально, если я просто использовал IEnumerable вместо ObservableCollection<something> , Может быть, я должен создать класс ObservableCollection, который не является универсальным (как в этот вопрос )?

1 Ответ

0 голосов
/ 09 декабря 2010

Создание неуниверсального класса 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}"/>
...