Данные связываются с частью коллекции - PullRequest
2 голосов
/ 07 июня 2011

У меня есть статическая коллекция предметов (скажем, от 1 до 100), которые я представляю в ComboBox. Я не могу связать эти элементы с ComboBox без проблем.

Мой вопрос заключается в том, как связать второй ComboBox с подмножеством этих элементов. Мне нужно, чтобы второй ComboBox был привязан к подмножеству элементов, оставшихся после выбора первого ComboBox. Например, первый ComboBox будет показывать 1,2,3 ..., 100. Если число 43 выбрано в первом ComboBox, то второй ComboBox должен показать 44,45, ..., 100.

Как это можно сделать и иметь второе обновление ComboBox, если первое изменяется без большого количества кода позади?

Ответы [ 5 ]

3 голосов
/ 07 июня 2011

Я бы сделал это с использованием шаблона MVVM. Создайте класс, который реализует INotifyChange, и предоставьте три свойства.

  • ICollection FullCollection
  • int FirstIndex
  • ICollection PartialCollection

Используйте этот класс в качестве DataContext для своего элемента управления и привяжите SelectedIndex первого поля со списком к свойству FirstIndex, ItemSource первого поля со списком к FullCollection и ItemSource из второй коллекции к PartialCollection (убедитесь, что режим привязки SelectedIndex является двухсторонним). Затем в наборе свойства FirstIndex установите свойство PartialCollection как хотите. Помните, что вы должны использовать NotifyPropertyChange для метода set каждого свойства. Надеюсь, что это поможет.

2 голосов
/ 07 июня 2011

Я бы пошел с дизайном MVVM, но если вы хотите просто провести тестирование и хотите увидеть быстрые результаты, не вдаваясь в шаблоны проектирования, то я бы предложил использовать что-то вроде CLINQ / BLINQ / Obtics фреймворк для усиления мощи LINQ при сохранении результатов для комбо-бокса.

Поскольку LoSciamano уже опубликовал ответ на это (пока я публиковал это!)Я не буду вдаваться в детали реализации MVVM

1 голос
/ 07 июня 2011

Я бы выставил первую коллекцию как ObservableCollection<T>, а вторую коллекцию как IEnumerable. Затем вы можете использовать представление коллекции по умолчанию для обработки событий, необходимых для повторной фильтрации вложенной коллекции.

class FilteredVM : ViewModelBase
{
    public ObservableCollection<MyVM> Items { get; private set; }
    public IEnumerable<MyVM> SubItems { get; private set; }

    public FilteredVM()
    {
        this.Items = new ObservableCollection<MyVM>();
        this.SubItems = Enumerable.Empty<MyVM>();

        var view = CollectionViewSource.GetDefaultView(this.Items);
        view.CurrentChanged += (sender, e) => { SetupFilter();  };
        view.CollectionChanged += (sender, e) => { SetupFilter(); };
    }

    private void SetupFilter()
    {
        var view = CollectionViewSource.GetDefaultView(this.Items);
        var current = view.CurrentItem;
        if (current != null)
        {
            this.SubItems = this.Items.Where((vm,idx) => idx > view.CurrentPosition);
        }
        else
        {
            this.SubItems = Enumerable.Empty<MyVM>();
        }

        this.OnPropertyChanged("SubItems");
    }
}

В качестве альтернативы, если вы хотите сохранить CollectionViewSource вне своей виртуальной машины:

class FilteredVM : ViewModelBase
{
    private MyVM selectedItem;
    public MyVM SelectedItem
    {
        get { return this.selectedItem; }
        set
        {
            if (value != this.selectedItem)
            {
                this.selectedItem = value;
                this.OnPropertyChanged("SelectedItem");
                this.SetupFilter();
            }
        }
    }

    public ObservableCollection<MyVM> Items { get; private set; }
    public IEnumerable<MyVM> SubItems { get; private set; }

    public FilteredVM()
    {
        this.Items = new ObservableCollection<MyVM>();
        this.SubItems = Enumerable.Empty<MyVM>();

        this.Items.CollectionChanged += (sender, e) => { this.SetupFilter(); };
    }

    private void SetupFilter()
    {
        if (this.SelectedItem != null)
        {
            var item = this.SelectedItem; // save for closure
            this.SubItems = this.Items.SkipWhile(vm => vm != item).Skip(1);
        }
        else
        {
            this.SubItems = Enumerable.Empty<MyVM>();
        }

        this.OnPropertyChanged("SubItems");
    }
}

Имейте в виду, что для этого потребуется SelectedItem для правильной привязки в представлении к модели представления. Первый из перечисленных подходов позволяет SelectedItem быть привязанным где угодно (или нигде).

0 голосов
/ 07 июня 2011

Вот конкретный пример (как обычно, может быть улучшен, но идея здесь):

Код модели представления:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        DataContext = new ViewModel();
    }
}


public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        Initialsource = new ObservableCollection<int>();
        for (int i = 0; i < 101; i++)
        {
            Initialsource.Add(i);
        }
    }

    private int _selectedsourceItem;
    public int SelectedsourceItem
    {
        get { return _selectedsourceItem; }
        set
        {
            _selectedsourceItem = value;
            SubsetSource = new ObservableCollection<int>(Initialsource.Where(p => p > _selectedsourceItem));
            InvokePropertyChanged(new PropertyChangedEventArgs("SubsetSource"));
            InvokePropertyChanged(new PropertyChangedEventArgs("SelectedsourceItem"));
        }
    }

    private ObservableCollection<int> _initialsource;
    public ObservableCollection<int> Initialsource
    {
        get { return _initialsource; }
        set
        {
            _initialsource = value;
            InvokePropertyChanged(new PropertyChangedEventArgs("Initialsource"));
        }
    }

    private ObservableCollection<int> _subsetSource;
    public ObservableCollection<int> SubsetSource
    {
        get { return _subsetSource ?? (_subsetSource = new ObservableCollection<int>()); }
        set
        {
            _subsetSource = value;
            InvokePropertyChanged(new PropertyChangedEventArgs("SubsetSource"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void InvokePropertyChanged(PropertyChangedEventArgs e)
    {

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, e);
    }
}

XAML:

<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
    <StackPanel Orientation="Horizontal">
        <ComboBox Width="100" ItemsSource="{Binding Initialsource}" SelectedItem="{Binding SelectedsourceItem, Mode=TwoWay}"></ComboBox>
        <ComboBox Width="100" ItemsSource="{Binding SubsetSource}"></ComboBox>
    </StackPanel>
</Grid>
0 голосов
/ 07 июня 2011

Имеют 2 наблюдаемые коллекции, чтобы при выборе элемента в 1-м поле он запускал метод, который очищает и повторно заполняет 2-ю коллекцию.Поскольку это observableCollection, оно автоматически отражается в графическом интерфейсе WPF

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...