多个ListBoxes SelectedItem绑定到同一属性

时间:2015-09-23 06:32:57

标签: c# wpf

我有两个列表框,它们都包含相同类型的项目,我将其SelectedItem属性绑定到我的ViewModel上的相同属性。我预计,当我在列表A中选择一些项目时,列表B中的选择将消失。但事实并非如此。我需要一个丑陋的解决方法来使它按预期工作。没有这种解决方法的任何提示如何使其工作?

XAML

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>

        <ListBox ItemsSource="{Binding Items1}" SelectedItem="{Binding SelectedItem}" ></ListBox>

        <ListBox Grid.Column="1" ItemsSource="{Binding Items2}" SelectedItem="{Binding SelectedItem}" ></ListBox>

        <Button Grid.Row="1" Content="NULL" Grid.ColumnSpan="2" Click="ButtonBase_OnClick"></Button>
    </Grid>
</Window>

C#

public partial class MainWindow : INotifyPropertyChanged
{
    private Item _selectedItem;
    public ObservableCollection<Item> Items1 { get; private set; }
    public ObservableCollection<Item> Items2 { get; private set; }
    public Item SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            // Uncomment this to make it work
            //_selectedItem = null;
            //OnPropertyChanged();
            _selectedItem = value;
            OnPropertyChanged();
        }
    }

    public MainWindow()
    {
        Items1 = new ObservableCollection<Item>();
        Items2 = new ObservableCollection<Item>();
        Items1.Add(new Item("A1"));
        Items1.Add(new Item("A2"));
        Items2.Add(new Item("B1"));
        Items2.Add(new Item("B2"));
        InitializeComponent();
    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        SelectedItem = null;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class Item
{
    public Item(string name)
    {
        Name = name;
    }

    string Name { get; set; }
}

2 个答案:

答案 0 :(得分:0)

为什么不将它们(TwoWay绑定)绑定到两个不同的属性(例如SelectedItem1SelectedItem2),然后:

public Item SelectedItem1
{
    get { return _selectedItem1; }
    set
    {            
        _selectedItem1 = value;
        OnPropertyChanged();

        if(value!=null)  //Here is the trick.
            SelectedItem2=null;

        OnPropertyChanged("SelectedItem");
    }
}

编辑:然后,对于其余的应用程序代码,您可以拥有如下所示的SelectedItem属性。另外,请不要忘记在OnPropertyChanged("SelectedItem")SelectedItem1

的setter中添加SelectedItem2
public Item SelectedItem
{
    get{return SelectedItem1 != null ? SelectedItem1 : SelectedItem2}
}

答案 1 :(得分:0)

如果这是一个丑陋的解决方法,那么请点击SelectionChanged事件:

    <ListBox x:Name="ListBoxA" ItemsSource="{Binding Items1}" SelectedItem="{Binding SelectedItem}" SelectionChanged="ListBox_SelectionChanged"></ListBox>
    <ListBox x:Name="ListBoxB" Grid.Column="1" ItemsSource="{Binding Items2}" SelectedItem="{Binding SelectedItem}" SelectionChanged="ListBox_SelectionChanged" ></ListBox>

    private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (sender == this.ListBoxA)
            this.ListBoxB.UnselectAll();
        else
            this.ListBoxA.UnselectAll();
    }

更好的是,使用附加行为来做同样的事情。