我有一个WPF窗口,其视图模型设置为其DataContext,并且具有一个带有DataTemplate的ListBox,其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>
当然,TeamBox的TeamName属性不会显示在ListBox项中,因为LisBox的每个项都是List.ItemTemplate的DataContext,它会覆盖Window的DataContext。
问题是:如何从ListBox的DataTemplate中数据绑定到视图模型(Window.DataContext)的TeamName属性?
答案 0 :(得分:14)
您也可以使用RelativeSource绑定,它并不复杂:
<TextBlock Text="{Binding Path=DataContext.TeamName, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Margin="4"/>
答案 1 :(得分:13)
我会将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>
答案 2 :(得分:1)
我为团队成员创建了一个视图模型,其中包含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 :(得分:0)
为什么不将DataContext绑定到团队,然后将你的itemsource绑定到team.members?
通常我会在我的代码隐藏中分配我的datacontext,但它仍然不适合你。
itemsouce =“{Binding Path =”team.Members“}
我想这与Aviad建议的完全相同。我只是在代码隐藏中分配datacontext。