【问题标题】:In WPF, how to databind to the Window DataContext from inside the DataTemplate of a contained ListBox?在 WPF 中,如何从包含的 ListBox 的 DataTemplate 内部数据绑定到 Window DataContext?
【发布时间】:2010-12-29 21:35:00
【问题描述】:

我有一个 WPF 窗口,其视图模型设置为其 DataContext,并且有一个 ListBox,其 DataTemplate 及其 ItemsSource 绑定到视图模型,如下例所示:

查看模型:

using System.Collections.Generic;

namespace Example
{
    class Member
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    class Team
    {
        private List<Member> members = new List<Member>();

        public string TeamName { get; set; }
        public List<Member> Members { get { return members; } }
    }
}

MainWindow.xaml:

<Window x:Class="Example.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:l="clr-namespace:Example" 
    Title="Example" Height="300" Width="300" Name="Main">

 <Window.DataContext>
  <l:Team TeamName="The best team">
   <l:Team.Members>
    <l:Member Name="John Doe" Age="23"/>
    <l:Member Name="Jane Smith" Age="20"/>
    <l:Member Name="Max Steel" Age="24"/>
   </l:Team.Members>
  </l:Team>
 </Window.DataContext>

 <ListBox ItemsSource="{Binding Path=Members}">
  <ListBox.ItemTemplate>
   <DataTemplate>
    <StackPanel Orientation="Horizontal">
     <TextBlock Text="{Binding Path=TeamName}" Margin="4"/>
     <TextBlock Text="{Binding Path=Name}" Margin="4"/>
    </StackPanel>
   </DataTemplate>
  </ListBox.ItemTemplate>
 </ListBox>
</Window>

当然,Team 类的 TeamName 属性不会显示在 ListBox 项中,因为 LisBox 的每个项都是 List.ItemTemplate 的 DataContext,它覆盖了 Window 的 DataContext。

问题是:如何从 ListBox 的 DataTemplate 中将数据绑定到视图模型 (Window.DataContext) 的 TeamName 属性?

【问题讨论】:

    标签: .net wpf data-binding mvvm datatemplate


    【解决方案1】:

    我会将 l:Team 声明提取到 Window.Resources 部分,并从 DataContext 和 DataTemplate 中引用它:

    <Window x:Class="Example.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:l="clr-namespace:Example" 
        Title="Example" Height="300" Width="300" Name="Main">
    
     <Window.Resources>
      <l:Team x:Key="data" TeamName="The best team">
       <l:Team.Members>
        <l:Member Name="John Doe" Age="23"/>
        <l:Member Name="Jane Smith" Age="20"/>
        <l:Member Name="Max Steel" Age="24"/>
       </l:Team.Members>
      </l:Team>
     <Window.Resources>
    
     <Window.DataContext>
         <StaticResource ResourceKey="data"/>
     </Window.DataContext>
    
     <ListBox ItemsSource="{Binding Path=Members}">
      <ListBox.ItemTemplate>
       <DataTemplate>
        <StackPanel Orientation="Horizontal">
         <TextBlock Text="{Binding Source={StaticResource data}, Path=TeamName}" Margin="4"/>
         <TextBlock Text="{Binding Path=Name}" Margin="4"/>
        </StackPanel>
       </DataTemplate>
      </ListBox.ItemTemplate>
     </ListBox>
    </Window>
    

    【讨论】:

    • +1。当然!我没有考虑将视图模型作为资源共享。我试图用 RelativeSources 和 FindAncestor 使问题复杂化,但没有成功。
    【解决方案2】:

    我会为团队成员创建一个视图模型,带有 TeamName 属性,类似于:

    class MemberViewModel
    {
        ...
        private TeamViewModel _team; 
        public string TeamName{ get { return _team.Name; } } 
    }
    
    class TeamViewModel
    {
        public List< MemberViewModel > Members { get{ ... } }
        // You may consider using ObservableCollection<> instead of List<>
    }
    

    然后您的 XAML 将与您的示例一样干净。使用 MVVM,您不需要在视图中使用任何奇异的绑定技巧。您需要的一切都应该通过视图模型提供。

    【讨论】:

    • 我将如何进行数据绑定?
    【解决方案3】:

    你也可以使用RelativeSource绑定,没那么复杂:

    <TextBlock Text="{Binding Path=DataContext.TeamName, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Margin="4"/>
    

    【讨论】:

      【解决方案4】:

      为什么不将 DataContext 绑定到团队,然后将 itemsource 绑定到 team.members?

      通常我在我的代码隐藏中分配我的数据上下文,但它仍然不应该对你有任何不同。

      itemsouce="{Binding Path="team.Members"}

      我想这和 Aviad 的建议是一样的。只是我在我的代码隐藏中分配数据上下文。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-27
        • 1970-01-01
        • 2014-07-30
        • 2013-02-04
        • 2017-06-05
        • 1970-01-01
        • 2011-11-27
        • 1970-01-01
        相关资源
        最近更新 更多