【问题标题】:How do you bind a ListBox's SelectedItem to another ListBox's SelectedItem's property?如何将 ListBox 的 SelectedItem 绑定到另一个 ListBox 的 SelectedItem 属性?
【发布时间】:2014-03-05 17:50:25
【问题描述】:

我的 UI 中有一个绑定到 List<Notification> Notifications { get; set; } 的 ListBox:

<ListBox ItemsSource="{Binding Notifications}"
         DisplayMemberPath="ServiceAddress"
         Name="NotificationsList"/>

通知有一个与之关联的过滤器标题:

public class Notification
{
    public string FilterTitle { get; set; }
    public string ServiceAddress { get; set; }
}

我的 UI 有另一个绑定到 List&lt;LogFilter&gt; Filters { get; set; } 的 ListBox:

<ListBox ItemsSource="{Binding Filters}"
         DisplayMemberPath="Title"
         Name="FiltersList"/>

您可以猜到,LogFilter 包含一个标题:

public class LogFilter
{
    public string Title { get; set; }
}

当我在我的 NotificationsList 中选择一个 Notification 时,我希望它根据 Notification 的 FilterTitle 和 LogFilter 的 Title 的映射在我的 FiltersList 中选择相应的 LogFilter。你怎么能通过绑定来做到这一点?

【问题讨论】:

    标签: c# .net wpf binding listbox


    【解决方案1】:

    首先,您需要将第一个列表框的SelectedValuePath 设置为FilterTitle:

    <ListBox ItemsSource="{Binding Notifications}"
             DisplayMemberPath="ServiceAddress" 
             Name="NotificationsList"
             SelectedValuePath="FilterTitle"/>
    

    使用ElementName 与第一个列表框的SelectedValue 绑定。此外,您还需要在此处将SelectedValuePath 设置为Title:

    <ListBox ItemsSource="{Binding Filters}"
             DisplayMemberPath="Title"
             Name="FiltersList"
             SelectedValuePath="Title"
             SelectedValue="{Binding SelectedValue, ElementName=NotificationsList, 
                                     Mode=OneWay}"/>
    

    【讨论】:

    • 但是现在,当您在第一个列表框中选择一个通知,然后在第二个列表框中更改过滤器时,它会取消选择您刚刚在第一个列表框中选择的通知,这不是我一直在追求的功能......我希望能够更改通知的过滤器。这可能吗?
    • 无法正确地获得正确,但我认为你只想要一种方法绑定,即选择任何通知时,选择相应的标题而不是反之亦然。如果是这种情况,您需要在绑定时设置Mode=OneWay。在答案中更新。
    • 它仍然缺少一些东西,因为它似乎不再从第一个列表框中正确更新。所以,我在第一个列表框中有一个通知列表,当我选择一个时,更新第二个列表框。当我在第二个列表框中更改选择时,我希望它将第一个列表框中的 FilterTitle 数据项(所选通知的一部分)更改为我在第二个列表框中选择的过滤器。 PS,到目前为止,我感谢您的帮助!
    • 这不是上述问题陈述的一部分。对于已发布的问题,上述解决方案将起作用。但是对于其他需要更新 FilterTitle 的情况,这在 XAML 中使用纯绑定是不可能的。您应该在 ViewModel 中有两个属性,并将两个列表框的 SelectedValue 绑定到各自的属性。当第二个列表框的选定值发生变化时,将第一个列表框的选定值的FilterTitle 设置为该值。
    • @Alexandru - 我在回答和 cmets 中提出了相同的建议。这里 - You should have two properties in ViewModel and bind SelectedValue of both listBoxes to respective properties. When selected value of second listBox changes, set the FilterTitle of selected Value for first listBox to that value. 有什么理由取消选择答案?
    【解决方案2】:

    正如您之前问题的其他答案中提到的,您真的应该考虑在 ViewModel 级别引入“选定项”的概念:

    public class MyViewModel
    {
         public List<Notification> Notifications {get;set;}
    
         //Here!
         public Notification SelectedNotification {get;set;} //INotifyPropertyChanged, etc here
    }
    

    然后将ListBox.SelectedItem绑定到那个:

    <ListBox ItemsSource="{Binding Notifications}"
             SelectedItem="{Binding SelectedNotification}"
             DisplayMemberPath="ServiceAddress"/>
    

    与其他 ListBox 相同:

    <ListBox ItemsSource="{Binding Filters}"
             SelectedItem="{Binding SelectedFilter}"
             DisplayMemberPath="Title"/>
    

    然后只需在更改 SelectedNotification 时找到合适的过滤器在 ViewModel 级别:

     private Notification _selectedNotification;
     public Notification SelectedNotification
     {
         get { return _selectedNotification; }
         set
         {
             _selectedNotification = value;
             NotifyPropertyChange("SelectedNotification");
    
             //here...
             if (value != null)     
                 SelectedFilter = Filters.FirstOrDefault(x => x.Title == value.FilterTitle);
         }
     }
    

    【讨论】:

    • 啊,是的,这正是你之前所说的。我现在看到了。
    • 我正在尝试这个,但我似乎无法让它工作,但我可以告诉事件正在触发......我很快就会发布一个堆栈问题......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 2010-12-26
    • 2011-01-02
    • 2011-02-24
    相关资源
    最近更新 更多