【问题标题】:Multiple Combobox with same Itemsource but the SelectedItem should be different - WPF具有相同Itemsource但SelectedItem应该不同的多个组合框 - WPF
【发布时间】:2016-09-14 18:53:30
【问题描述】:

目标是拥有多个Combobox,一旦该项目在Combobox中的任何一个中被选中,就应该从其他Comboboxes中移除或隐藏以供选择。

只要在任何Comboboxes 上更改选择,我就可以更改源。但是问题是当我从ItemsSource 中删除所选项目时,项目已从所有来源中删除,包括我选择的来源。

这里是示例

xaml

<StackPanel>
    <ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
    <ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
    <ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
    <ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
</StackPanel>

代码隐藏

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        ObservableCollection<string> s = new ObservableCollection<string>();
        s.Add("item1");
        s.Add("item2");
        s.Add("item3");
        s.Add("item4");
        s.Add("item5");
        s.Add("item6");

        DataContext = new MainViewModel() { ComboboxItems = s , SelectedItem = "item2" };

    }
}

public class MainViewModel : INotifyPropertyChanged
{
    private ObservableCollection<string> comboboxitems;

    public ObservableCollection<string> ComboboxItems
    {
        get { return comboboxitems; }  
        set { comboboxitems = value; OnPropertyChanged("ComboboxItem"); }
    }

    private string _selectedItem;

    public string SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value;
            comboboxitems.Remove(value);  //here removing selected item from itemssource
            OnPropertyChanged("SelectedItem");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propname)
    {
        if(PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propname));
    }
}

我知道每个Combobox 可以有多个集合,但如果Combobox 的数量增加,这可能会占用大量内存。

希望,在 WPF 中应该有一种简单的方法来实现这一点。

【问题讨论】:

  • 好吧,在这种情况下,您必须创建多个 SelectedItem 属性,我相信每个组合框都有一个。例如SelectedItem1、SelectedItem2等,但ItemsSource可以共享。
  • 使用 CollectionView 或 CollectionViewSource- 代表您的实际来源。这将允许通过 View 属性共享公共源,并且您可以为每个 CollectionView 拥有不同的选定项(CurrentItem)。
  • @adminSoftDK 是的,我们可以。但是如何从其他Combobox 上删除或限制该项目?
  • 每个组合框都需要一个样式和触发器来执行此操作。因此,如果当前项目等于 OtherSelectedItem 则对该项目应用一些东西。我现在没有时间制作代码示例。但希望你能明白。

标签: wpf xaml data-binding combobox observablecollection


【解决方案1】:

您可以为每个ComboBox 定义不同的SelectedItem,然后为每个ComboBox 创建一个SharedItemSource 的包装器,以过滤掉其他ComboBox 的SelectedItem。例如:

C#:

    public IEnumerable<string> ComboboxItems1
    {
        get
        {
            return ComboboxItems.Where(x => x != SelectedItem2 && x != SelectedItem3);
        }
    }

    public string SelectedItem1
    {
        get { return _selectedItem1; }
        set
        {
            if (_selectedItem1 != value)
            {
                _selectedItem1 = value;
                RaisePropertyChanged("SelectedItem1");
                RaisePropertyChanged("ComboboxItems2"); //raise propertychanged to refresh GUI 
                RaisePropertyChanged("ComboboxItems3");
            }
        }
    }       

    public IEnumerable<string> ComboboxItems2
    {
        get
        {
            return ComboboxItems.Where(x => x!=SelectedItem1&&x!=SelectedItem3);
        }
    }

    public string SelectedItem2
    {
        get { return _selectedItem2; }
        set
        {
            if (_selectedItem2 != value)
            {
                _selectedItem2 = value;                   
                RaisePropertyChanged("SelectedItem2");
                RaisePropertyChanged("ComboboxItems1"); //raise propertychanged to refresh GUI
                RaisePropertyChanged("ComboboxItems3");
            }
        }
    }

    public IEnumerable<string> ComboboxItems3
    {
        get
        {
            return ComboboxItems.Where(x => x != SelectedItem1 && x != SelectedItem2);
        }
    }

    public string SelectedItem3
    {
        get { return _selectedItem3; }
        set
        {
            if (_selectedItem3 != value)
            {
                _selectedItem3 = value;                 
                RaisePropertyChanged("SelectedItem3");
                RaisePropertyChanged("ComboboxItems1"); //raise propertychanged to refresh GUI
                RaisePropertyChanged("ComboboxItems2");
            }
        }
    }

XAML:

<ComboBox SelectedItem="{Binding SelectedItem1}" ItemsSource="{Binding ComboboxItems1}" />
<ComboBox  SelectedItem="{Binding SelectedItem2}" ItemsSource="{Binding ComboboxItems2}" />
<ComboBox  SelectedItem="{Binding SelectedItem3}" ItemsSource="{Binding ComboboxItems3}" />

【讨论】:

  • 。我导致Stack overflow 异常,因为ItemsSource 刷新SelectedItem1。
  • 能否设置一个断点并尝试获取有关异常的更多信息。
  • 是的。在OnPropertyChanged("ComboboxItems1"); 上,它再次触发SelectedItem1 的Set,从而导致死锁。
  • 能否贴出相关代码,从我上面贴的代码中是不可能的。
  • 我认为在您的代码中,我们在Combobox 中有一个ItemsSource,在GUI 中设置SelectedItem 会触发VM 上SelectedItem 属性的Set。现在,在Set 中,我们再次更改相同Combobox 的ItemsSource,以前的SelectedItem 现在不存在,因为它被添加到C#Remove。所以它再次触发SelectedItem 属性的Set 并且循环继续。 .
猜你喜欢
  • 2016-04-27
  • 1970-01-01
  • 2013-11-22
  • 2012-04-09
  • 1970-01-01
  • 1970-01-01
  • 2015-06-30
  • 2022-10-18
  • 2011-05-19
相关资源
最近更新 更多