【问题标题】:Multiple ListBoxes SelectedItem Binding to same property多个 ListBoxes SelectedItem 绑定到同一属性
【发布时间】:2015-09-23 06:32:57
【问题描述】:

我有两个列表框,它们都包含相同类型的项目,并且它们的 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; }
}

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

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

    public Item SelectedItem1
    {
        get { return _selectedItem1; }
        set
        {            
            _selectedItem1 = value;
            OnPropertyChanged();
    
            if(value!=null)  //Here is the trick.
                SelectedItem2=null;
    
            OnPropertyChanged("SelectedItem");
        }
    }
    

    编辑: 然后对于您的应用程序代码的其余部分,您可以拥有一个SelectedItem 属性,如下所示。另外不要忘记在SelectedItem1 和SelectedItem2 的setter 中添加OnPropertyChanged("SelectedItem")

    public Item SelectedItem
    {
        get{return SelectedItem1 != null ? SelectedItem1 : SelectedItem2}
    }
    

    【讨论】:

    • 因为对于其余的应用程序逻辑,这无关紧要,代码会更简单,只有一个绑定属性。
    • 谢谢。仍然是 3 个属性对 1 个属性。我也想知道为什么 WPF 会这样。
    【解决方案2】:

    如果你想要一个丑陋的解决方法,然后点击 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();
        }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-26
      • 1970-01-01
      • 2016-02-22
      相关资源
      最近更新 更多