WPF Single selection between two ListBoxes

2019-03-27 06:55发布

问题:

I'm having the following problem: I have two ListBox, with two different ItemSource, but both of them have the same binding for the SelectedItem, because I was trying to perform a single selection between these two lists.

Here's an image that better shows the problem:

What would I like to do? Every time I select one item from the first list (in red), it should deselect the SelectedItem from the second list (in black), and vice versa. That's why I'm using the same binding for both of them. I really don't know if it's the better way to do it, but it should work like that.

Could you help me?

回答1:

Try using SelectedValue instead, this will sop the behaviour you are seeing

 <ListBox SelectedValue="{Binding MySelectedItem}" />

It seems that SelectedItem does not deselect is the selected item is not found in the list, But SelectedValue does seem to deselect it, not sure why

You can see the diffence in this sample app:

xaml:

<Window x:Class="WpfApplication11.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="184" Width="208" x:Name="UI">
    <StackPanel DataContext="{Binding ElementName=UI}">
        <TextBlock Text="SelectedValue" />
        <StackPanel Orientation="Horizontal" Height="60" >
            <ListBox ItemsSource="{Binding MyItemSource1}" SelectedValue="{Binding MySelectedValue}" Width="100" />
            <ListBox ItemsSource="{Binding MyItemSource2}" SelectedValue="{Binding MySelectedValue}" Width="100" />
        </StackPanel>
        <TextBlock Text="SelectedItem" />
        <StackPanel Orientation="Horizontal" Height="60"  >
            <ListBox ItemsSource="{Binding MyItemSource1}" SelectedItem="{Binding MySelectedItem}" Width="100" />
            <ListBox ItemsSource="{Binding MyItemSource2}" SelectedItem="{Binding MySelectedItem}" Width="100" />
        </StackPanel>
    </StackPanel>
</Window>

code:

public partial class MainWindow : Window , INotifyPropertyChanged
{
    private CustomObject _mySelectedItem;
    private CustomObject _mySelectedValue;
    private ObservableCollection<CustomObject> _items = new ObservableCollection<CustomObject>();
    private ObservableCollection<CustomObject> _items2 = new ObservableCollection<CustomObject>();

    public MainWindow()
    {
        InitializeComponent();
        MyItemSource1.Add(new CustomObject { Name = "Stack" });
        MyItemSource1.Add(new CustomObject { Name = "Overflow" });
        MyItemSource2.Add(new CustomObject { Name = "Stack" });
        MyItemSource2.Add(new CustomObject { Name = "Overflow" });
    }

    public ObservableCollection<CustomObject> MyItemSource1
    {
        get { return _items; }
        set { _items = value; }
    }

    public ObservableCollection<CustomObject> MyItemSource2
    {
        get { return _items2; }
        set { _items2 = value; }
    }

    public CustomObject MySelectedItem
    {
        get { return _mySelectedItem; }
        set { _mySelectedItem = value; NotifyPropertyChanged("MySelectedItem"); }
    }

    public CustomObject MySelectedValue
    {
        get { return _mySelectedValue; }
        set { _mySelectedValue = value; NotifyPropertyChanged("MySelectedValue"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

public class CustomObject
{
    public string Name { get; set; }
    public override string ToString()
    {
        return Name;
    }
}



回答2:

What I had to do was at first pass null to the property and notify the changing, and then I passed the real value to the property and notified the changing to the view. Like that:

protected Bar selectedItem;
public Bar SelectedItem{
    get
    {
        return selectedItem;
    }
    set
    {
        selectedItem = null;
        NotifyPropertyChanged("SelectedItem");

        selectedItem = value;
        NotifyPropertyChanged("SelectedItem");
    }

I got this answer and example from this question.