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

时间:2017-07-07 12:00:06

标签: wpf combobox

我有一个简单的课程:

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

我在Mainwindow.xaml.cs中有这个类的列表:

public List<Item> AllItems=GetAllItems();

我在Mainwindow.xaml.cs中有4个Item类的属性:

public Item Item1{get;set;}
public Item Item2{get;set;}
public Item Item3{get;set;}
public Item Item4{get;set;}

此列表: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}"/>

我有四个TextBox,对应于这四个Comboboxes:

<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? 到目前为止,我已经尝试将所选项目和整个列表发送到MultivalueConverter并消除/添加项目到列表本身,但这似乎太meesy.Any其他更好的主意将不胜感激。

3 个答案:

答案 0 :(得分:0)

您可以为每个ComboBox提供单独的列表。然后,您可以为每个事件添加LostFocus事件处理程序。您可以使用它来重新填充其他ComboBox的列表以排除选择。

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

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

就个人而言,我采用第二种方法;也许在文本框上方有一条消息,表明选择必须是唯一的。您可以指出任何错误并阻止任何依赖于选择的操作,但这些操作无效,但您不必经常更新数据,这可能会导致更流畅的用户界面。

答案 1 :(得分:0)

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

 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;
        }

您可以在选定的combox事件中编写此代码。

我猜你可以使用XAML中的触发器编写相同的逻辑

答案 2 :(得分:0)

您应该在视图模型中处理这种逻辑。这是一个给你一个想法的例子:

查看型号:

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));
    }
}

<强> XAML:

<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}"/>