如何防止用户从wpf中的多个组合框中选择相同的值

如何防止用户从wpf中的多个组合框中选择相同的值,wpf,combobox,Wpf,Combobox,我有一个简单的类: public class Item { public int ID{get;set;} public string Name{get;set;} } public List<Item> AllItems=GetAllItems(); public Item Item1{get;set;} public Item Item2{get;set;} public Item Item3{get;set;} public Item Item4{get;set

我有一个简单的类:

public class Item
{
   public int ID{get;set;}
   public string Name{get;set;}
}
public List<Item> AllItems=GetAllItems();
public Item Item1{get;set;}
public Item Item2{get;set;}
public Item Item3{get;set;}
public Item Item4{get;set;}
<TextBlock x:Name="txtName1" Text="{Binding Item1.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName2" Text="{Binding Item2.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName3" Text="{Binding Item3.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName4" Text="{Binding Item4.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
我在Mainwindow.xaml.cs中有一个此类列表,如下所示:

public class Item
{
   public int ID{get;set;}
   public string Name{get;set;}
}
public List<Item> AllItems=GetAllItems();
public Item Item1{get;set;}
public Item Item2{get;set;}
public Item Item3{get;set;}
public Item Item4{get;set;}
<TextBlock x:Name="txtName1" Text="{Binding Item1.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName2" Text="{Binding Item2.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName3" Text="{Binding Item3.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName4" Text="{Binding Item4.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
此列表:AllItems数据绑定到四个组合框,如下所示:

 <ComboBox x:Name="cmbCode1" ItemsSource="{Binding AllItems}" DisplayMemberPath="ID" SelectedValuePath="ID" SelectedValue="{Binding Item1.ID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Item1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
 <ComboBox x:Name="cmbCode2" ItemsSource="{Binding AllItems}"  DisplayMemberPath="ID" SelectedValuePath="ID" SelectedValue="{Binding Item1.ID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Item1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
 <ComboBox x:Name="cmbCode3" ItemsSource="{Binding AllItems}" DisplayMemberPath="ID" SelectedValuePath="ID" SelectedValue="{Binding Item1.ID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Item1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
 <ComboBox x:Name="cmbCode4" ItemsSource="{Binding AllItems}" DisplayMemberPath="ID" SelectedValuePath="ID" SelectedValue="{Binding Item1.ID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Item1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>

我有四个文本框对应这四个组合框:

public class Item
{
   public int ID{get;set;}
   public string Name{get;set;}
}
public List<Item> AllItems=GetAllItems();
public Item Item1{get;set;}
public Item Item2{get;set;}
public Item Item3{get;set;}
public Item Item4{get;set;}
<TextBlock x:Name="txtName1" Text="{Binding Item1.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName2" Text="{Binding Item2.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName3" Text="{Binding Item3.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName4" Text="{Binding Item4.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>

我想要的是,用户永远不能从多个组合框中选择相同的ID。 是否有一些简单的方法可以做到这一点,特别是仅使用xaml?如何隐藏或显示从其他组合框中选择/未选择的项目,以便用户无法从多个组合框中选择相同的ID?
到目前为止,我已尝试将所选项目和整个列表发送到多值转换器,并将项目删除/添加到列表中,但这似乎过于简单。如果有其他更好的想法,我们将不胜感激。

您可以为每个组合框创建单独的列表。然后,您可以向它们中的每一个添加一个事件处理程序。您可以使用它来重新填充其他组合框的列表,以排除选择

例如,如果我的列表中有5项;最初,我可以在任何组合框中选择全部5个。当我在ComboBox 1中选择Item1时,LostFocus事件处理程序将更新ComboBox 2-4后面的列表以删除Item1。然后,当我在ComboBox 2中选择Item2时,LostFocus事件处理程序将更新ComboBox 3和4后面的列表以删除Item2。等等

另一种方法可能是让用户选择他们喜欢的任何内容,然后对所选值进行某种验证,以确保它们是唯一的。这是你的一些选择


就我个人而言,我会选择第二种方法;可能在文本框上方有一条消息,指示所选内容必须是唯一的。当选择无效时,您可以指示任何错误并阻止依赖该选择的任何操作,但您不必不断更新数据,这可能会导致更平滑的用户界面。

您可以使用该代码在不同的组合框中隐藏所选项

 for (int count = 0; count <= cmb1.Items.Count -1; count++)
    {

    if((ComboBoxItem)(cmb1.Items[count])).SelectedValue==TextBox1.Text)
 ((ComboBoxItem)(cmb1.Items[count])).Visibility = System.Windows.Visibility.Collapsed;
        }

for(int-count=0;count您应该在视图模型中处理这种逻辑。下面是一个示例,可以让您了解:

查看模型:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        AllItems = new List<Item>() { new Item { Name = "1" }, new Item { Name = "2" }, new Item { Name = "3" }, new Item { Name = "4" } };
    }

    public List<Item> AllItems { get; set; }

    private Item _item1;
    public Item Item1
    {
        get { return _item1; }
        set
        {
            _item1 = value;
            NotifyPropertyChanged();
            if (value != null)
                value.CanSelect = false;
        }
    }

    private Item _item2;
    public Item Item2
    {
        get { return _item2; }
        set
        {
            _item2 = value;
            NotifyPropertyChanged();
            if (value != null)
                value.CanSelect = false;
        }
    }

    private Item _item3;
    public Item Item3
    {
        get { return _item3; }
        set
        {
            _item3 = value; NotifyPropertyChanged();
            if (value != null)
                value.CanSelect = false;
        }
    }

    private Item _item4;
    public Item Item4
    {
        get { return _item4; }
        set
        {
            _item4 = value;
            NotifyPropertyChanged();
            if (value != null)
                value.CanSelect = false;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

    }
}

public class Item : INotifyPropertyChanged
{
    public int ID { get; set; }
    public string Name { get; set; }

    private bool _canSelect = true;
    public bool CanSelect
    {
        get { return _canSelect; }
        set { _canSelect = value; NotifyPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
<Style x:Key="icstyle" TargetType="ComboBoxItem">
    <Setter Property="IsEnabled" Value="{Binding CanSelect}" />
</Style>
...
<ComboBox x:Name="cmbCode1" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item1}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
<ComboBox x:Name="cmbCode2" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item2}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
<ComboBox x:Name="cmbCode3" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item3}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
<ComboBox x:Name="cmbCode4" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item4}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
public分部类主窗口:窗口,INotifyPropertyChanged
{
公共主窗口()
{
初始化组件();
DataContext=this;
AllItems=new List(){new Item{Name=“1”},new Item{Name=“2”},new Item{Name=“3”},new Item{Name=“4”};
}
公共列表所有项{get;set;}
私人物品_item1;
公共项目1
{
获取{return\u item1;}
设置
{
_第1项=价值;
NotifyPropertyChanged();
if(值!=null)
value.CanSelect=false;
}
}
私人物品_物品2;
公共项目2
{
获取{return\u item2;}
设置
{
_第2项=价值;
NotifyPropertyChanged();
if(值!=null)
value.CanSelect=false;
}
}
私人项目_项目3;
公共项目3
{
获取{return\u item3;}
设置
{
_item3=值;NotifyPropertyChanged();
if(值!=null)
value.CanSelect=false;
}
}
私人项目_项目4;
公共项目4
{
获取{return\u item4;}
设置
{
_第4项=价值;
NotifyPropertyChanged();
if(值!=null)
value.CanSelect=false;
}
}
公共事件属性更改事件处理程序属性更改;
私有void NotifyPropertyChanged([CallerMemberName]字符串propertyName=”“)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共类项目:INotifyPropertyChanged
{
公共int ID{get;set;}
公共字符串名称{get;set;}
私有bool_canSelect=true;
公共图书馆可供选择
{
获取{return\u canSelect;}
设置{u canSelect=value;NotifyPropertyChanged();}
}
公共事件属性更改事件处理程序属性更改;
私有void NotifyPropertyChanged([CallerMemberName]字符串propertyName=”“)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
XAML:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        AllItems = new List<Item>() { new Item { Name = "1" }, new Item { Name = "2" }, new Item { Name = "3" }, new Item { Name = "4" } };
    }

    public List<Item> AllItems { get; set; }

    private Item _item1;
    public Item Item1
    {
        get { return _item1; }
        set
        {
            _item1 = value;
            NotifyPropertyChanged();
            if (value != null)
                value.CanSelect = false;
        }
    }

    private Item _item2;
    public Item Item2
    {
        get { return _item2; }
        set
        {
            _item2 = value;
            NotifyPropertyChanged();
            if (value != null)
                value.CanSelect = false;
        }
    }

    private Item _item3;
    public Item Item3
    {
        get { return _item3; }
        set
        {
            _item3 = value; NotifyPropertyChanged();
            if (value != null)
                value.CanSelect = false;
        }
    }

    private Item _item4;
    public Item Item4
    {
        get { return _item4; }
        set
        {
            _item4 = value;
            NotifyPropertyChanged();
            if (value != null)
                value.CanSelect = false;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

    }
}

public class Item : INotifyPropertyChanged
{
    public int ID { get; set; }
    public string Name { get; set; }

    private bool _canSelect = true;
    public bool CanSelect
    {
        get { return _canSelect; }
        set { _canSelect = value; NotifyPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
<Style x:Key="icstyle" TargetType="ComboBoxItem">
    <Setter Property="IsEnabled" Value="{Binding CanSelect}" />
</Style>
...
<ComboBox x:Name="cmbCode1" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item1}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
<ComboBox x:Name="cmbCode2" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item2}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
<ComboBox x:Name="cmbCode3" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item3}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
<ComboBox x:Name="cmbCode4" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item4}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>

...

XAML是一种标记语言……它不是用来实现这种逻辑的。您应该使用编程语言来实现这一点。@mm8:由于我对WPF的了解有限,目前我正在使用多值转换器,在更改每个SelectedItem时,我发送的不是一个而是全部四个列表,并且正在执行所有的加分s到那里的列表..tx用于那里的更新。至少现在我不会花时间去想它是否可能在XAML中实现,我不知道..-)。。