В WPF, как связать с данными к Окну DataContext из DataTemplate содержавшего ListBox?

Я имею Окно WPF с целью образцовый набор как его DataContext и имею ListBox с DataTemplate и его ItemsSource, связанным с моделью представления, как в следующем примере:

Модель View:

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>

Конечно, свойство TeamName класса Команды не отображено в объектах ListBox, потому что каждым объектом LisBox является DataContext Списка. ItemTemplate, и это переопределяет DataContext Окна.

Вопрос: Как я связываю с данными к свойству TeamName модели представления (Окно. DataContext) из DataTemplate ListBox?

8
задан Yael 8 January 2017 в 19:51
поделиться

4 ответа

Я бы извлек объявление 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>
14
ответ дан 5 December 2019 в 05:34
поделиться

Я бы создал модель представления для члена команды с 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 вам не понадобятся какие-либо экзотические трюки привязки в представлении. Все, что вам нужно, должно быть доступно через модель просмотра.

1
ответ дан 5 December 2019 в 05:34
поделиться

Вы также можете использовать привязку RelativeSource, это не так уж и сложно:

<TextBlock Text="{Binding Path=DataContext.TeamName, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Margin="4"/>
15
ответ дан 5 December 2019 в 05:34
поделиться

Почему вы не связываете свой DataContext с командой, а затем не связываете свой источник данных с team.members?

обычно я назначаю свой dataacontext в коде позади, но он все равно не должен быть для вас равнозначным.

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

Я думаю, что на самом деле это то же самое, что и то, что предложил Aviad. Просто я присваиваю текст данных в своем коде.

0
ответ дан 5 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: