Ограничение выбора WPF ComboBox из известного списка - PullRequest
1 голос
/ 03 мая 2011

Я разрабатываю пользовательский элемент управления WPF, содержащий ComboBox.Варианты ComboBox - это единицы времени, то есть секунды, минуты, часы, дни и т. Д., И они предоставляются через таблицу поиска в базе данных.Каждый выбор связан с соответствующим значением перечисления, доступным из перечисления с именем TimeInterval.Другие функции нашего приложения будут принимать решения на основе выбранного выбора.

Разработчики, использующие этот элемент управления, должны иметь возможность ограничивать количество единиц времени, доступных для выбора.Например, при определенных обстоятельствах может оказаться целесообразным показывать минуты и секунды в списке.Другие разработчики могут захотеть предоставить полный список.

Я пытаюсь найти элегантный способ сделать это, но затрудняюсь.Моей первой мыслью было как-то использовать Flags (FlagsAttribute) поверх перечисления, но я не был уверен, как к нему подойти.

Идеальным будет чистый подход XAML, но я также открыт для решений кода.

Заранее спасибо.

1 Ответ

1 голос
/ 03 мая 2011

Вы можете использовать преимущества CollectionView для достижения ожидаемого поведения.

В этом случае ваш UserControl предоставляет свойство зависимостей FilterTimeInterval, тип которого Predicate<TimeInterval>. Когда это свойство изменяется, вы устанавливаете ICollectionView.Filter свойство для сбора ваших предметов. Если сторонний разработчик использует ваш элемент управления и хочет ограничить элементы комбинированного списка, он должен просто связать соответствующий предикат со свойством FilterTimeInterval.

Вот некоторая демонстрация (чтобы упростить кодирование, комбинированный список содержит строковые элементы).

XAML вашего контроля:

<UserControl x:Class="Test.TimeIntervalsControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <ComboBox ItemsSource="{Binding Items}"/>
    </Grid>
</UserControl>

Код вашего контроля с объявлением свойства зависимостей:

public partial class TimeIntervalsControl : UserControl
{
    public TimeIntervalsControl()
    {
        InitializeComponent();
        this.Model = new TimeIntervalsViewModel();
    }

    public TimeIntervalsViewModel Model
    {
        get
        {
            return (TimeIntervalsViewModel)this.DataContext;
        }
        set
        {
            this.DataContext = value;
        }
    }

    public Predicate<string> FilterTimeInterval
    {
        get
        {
            return (Predicate<string>)this.GetValue(TimeIntervalsControl.FilterTimeIntervalProperty);
        }
        set
        {
            this.SetValue(TimeIntervalsControl.FilterTimeIntervalProperty, value);
        }
    }

    public static readonly DependencyProperty FilterTimeIntervalProperty =
        DependencyProperty.Register("FilterTimeInterval",
            typeof(Predicate<string>),
            typeof(TimeIntervalsControl),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None,   
                (d, e) =>
                {
                    var control = (TimeIntervalsControl)d;
                    var view = CollectionViewSource.GetDefaultView(control.Model.Items);
                    if (e.NewValue == null)
                    {
                        view.Filter = null;
                    }
                    else
                    {
                        view.Filter = o => ((Predicate<string>)e.NewValue)((string)o);
                    }
                }));
}

ViewModel вашего управления:

public sealed class TimeIntervalsViewModel : ObservableObject
{
    private readonly string[] _items = new string[] {"Years","Month","Days","Hours","Minutes","Seconds"};

    public IEnumerable<string> Items
    {
        get
        {
            return this._items;
        }
    }
}

Управление готово, пришло время использовать его и ограничить некоторые элементы. В этом примере я блокирую каждый элемент, кроме «Дней».

Использование вашего элемента управления в XAML выглядит следующим образом:

<UserControl x:Class="Test.StartupView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:self="clr-namespace:Test"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Name="Root">
    <WrapPanel>
        <self:TimeIntervalsControl FilterTimeInterval="{Binding Path=DataContext.JustDaysFilter, ElementName=Root}"/>
    </WrapPanel>
</UserControl>

И, конечно, мы должны подготовить свойство JustDaysFilter в модели представления:

public class StartupViewModel
{
    private readonly Predicate<string> _justDaysFilter = s => s == "Days";
    public Predicate<string> JustDaysFilter
    {
        get
        {
            return this._justDaysFilter;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...