Как привязать одну ObservableCollection как ItemsSource к различным комбинированным спискам (моделям) при использовании wpf ItemsControl с шаблоном MVVM? - PullRequest
1 голос
/ 15 апреля 2019

Я динамически создаю список комбинированных списков для разных моделей, используя элемент wpf ItemsControl, используя шаблон MVVM.Я хочу иметь логику, например, если я выберу элемент в одном из комбинированных списков, то во всех остальных он не появится.У меня возникают трудности с этим, когда я использую ItemsControl (ItemsSource - список моих моделей) и создаю для него элементы в VievModel - привязка не работает, она работает только тогда, когда у меня есть список элементов comboBox для каждой из моделей (класс Model), а недля всех комбинированных списков (в классе ViewModel).Могу ли я иметь, например, 1 ObservableCollection для элементов комбинированного списка в ViewModel и использовать также ItemsControl для создания комбинированного списка?

My View:

    <ItemsControl ItemsSource="{Binding Items}" Grid.Row="1">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"  />
                            <ColumnDefinition Width="*"  />
                        </Grid.ColumnDefinitions>
                        <Label  Content="{Binding Name}" Grid.Column="0" />
                        <ComboBox  ItemsSource="{Binding ComboBoxItems}" Grid.Column="1"  
                                   SelectedItem="{Binding SelectedItem}"/>
</Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

ViewModel:

public ObservableCollection<Model> Items { get; set; }

// if I add here public ObservableCollection<string> ComboBoxItems { get; set; } 
// binding isn't working, so I add it to Model class, but in it it does not work as I need.

public ViewModel()
{
Items = new ObservableCollection<Model>();
Items.Add(new Model {Name = "11111"});
Items.Add(new Model {Name = "22222"});
}

Модель:

 public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged("Name");
        }
    }
 public string SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value;
            OnPropertyChanged("SelectedItem");
        }
    }

public ObservableCollection<string> ComboBoxItems {get;set;}

public Model()
{
ComboBoxItems = new ObservableCollection<string>();
ComboBoxItems.Add("q");
ComboBoxItems.Add("w");
ComboBoxItems.Add("e");
ComboBoxItems.Add("r");
ComboBoxItems.Add("t");
ComboBoxItems.Add("y");
}

Ответы [ 2 ]

0 голосов
/ 15 апреля 2019

Для достижения своей цели вы можете отфильтровать представление ComboBoxItems. Вы можете сделать это одним способом с одним исходным кодом, для чего вам нужно всего лишь изменить конструктор ViewModel, например:

public ViewModel()
{
    Items = new ObservableCollection<Model>();
    Items.Add(new Model {Name = "11111"});
    Items.Add(new Model {Name = "22222"});
    Items.Add(new Model {Name = "33333"});

    foreach (var item in Items)
    {
        CollectionViewSource.GetDefaultView(item.ComboBoxItems).Filter =
            (x) => !Items.Where((y) => y != item).Select(y => y.SelectedItem).Any(y => y == (string)x);

        item.PropertyChanged += (s, e) =>
        {
            foreach (var obj in Items.Where((x) => x != item).Select(x => x.ComboBoxItems))
                CollectionViewSource.GetDefaultView(obj).Refresh();
        };
    }    
}

Или вы также можете сделать это в режиме просмотра нескольких источников из одного источника, что позволит вам отказаться от вашей модели.

public class ViewModel
{
    private List<string> _comboBoxItems = new List<string> { "q", "w", "e", "r", "t", "y" };
    private List<ICollectionView> _comboBoxViews = new List<ICollectionView>();

    public ObservableCollection<string> Names { get; set; } = new ObservableCollection<string> { "111", "222", "333" };

    public ICollectionView ComboBoxView
    {
        get
        {
            var view = new CollectionViewSource { Source = _comboBoxItems}.View;
            _comboBoxViews.Add(view);
            view.MoveCurrentToPosition(-1);

            view.Filter = (x) => !_comboBoxViews.Where(y => y != view).Any(y => (string)y.CurrentItem == (string)x);

            view.CurrentChanged += (s, e) =>
            {
                foreach (var v in _comboBoxViews.Where(x => x != view))
                    v.Refresh();
            };

            return view;
        }
    }
}

<ItemsControl ItemsSource="{Binding Names}" Grid.Row="1">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"  />
                    <ColumnDefinition Width="*"  />
                </Grid.ColumnDefinitions>
                <Label  Content="{Binding}" Grid.Column="0" />
                <ComboBox  ItemsSource="{Binding DataContext.ComboBoxView, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
                           Grid.Column="1"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
0 голосов
/ 15 апреля 2019

1 ObservableCollection для элементов comboBox во ViewModel, а также используйте ItemsControl для создания comboBoxes Это означает, что вы хотите связать одну и ту же ObservableCollection с ur ItemsControl и ComboBox, если нет, пожалуйста, дайте мне знать в комментарии

Ans

   <ItemsControl ItemsSource="{Binding Items}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"  />
                            <ColumnDefinition Width="*"  />
                        </Grid.ColumnDefinitions>
                        <Label  Content="{Binding Name}" Grid.Column="0" />
                        <ComboBox  ItemsSource="{Binding Items ,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ItemsControl}}" Grid.Column="1"  
                                  DisplayMemberPath="Name" SelectedItem="{Binding SelectedItem}"/>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

я связал Items до ComboBox

...