2009-12-24 16 views
7

I tienen una ventana WPF con un modelo de vista establecer como su DataContext, y tienen un ListBox con un DataTemplate y su ItemsSource unido al modelo de vista, como en el siguiente ejemplo:En WPF, ¿cómo enlazar datos con Window DataContext desde el DataTemplate de un ListBox contenido?

Ver modelo:

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> 

por supuesto, la propiedad teamname de la clase de equipo no se muestra en los artículos ListBox porque cada elemento de la LisBox es el DataContext de la List.ItemTemplate, y se anula t El DataContext de la ventana.

La pregunta es: ¿Cómo puedo enlazar datos con la propiedad TeamName del modelo de vista (Window.DataContext) desde el DataTemplate de ListBox?

Respuesta

12

me extraer el l: declaración del equipo a la sección Window.Resources, y hacer referencia a ella desde dentro de la DataContext y 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> 
+0

1. Por supuesto! No había pensado en compartir el modelo de visualización como un recurso. Estaba intentando complicar las definiciones con RelativeSources y FindAncestor sin éxito. –

+0

Vaya, lo votaría si tuviera suficiente reputación. –

1

que crearía un modelo de vista de un miembro del equipo, con TeamName una propiedad, algo así como:

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<> 
} 

Luego, su XAML se verá tan limpio como en su ejemplo. Con MVVM, no debería necesitar trucos de enlace exóticos en la vista. Todo lo que necesita debe estar disponible a través del modelo de vista.

+1

Y cómo haría los enlaces de datos. ? –

14

También puede utilizar el enlace de RelativeSource, no es tan complicado:

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

¿Por qué no vincular a su DataContext al equipo, luego hacer su ItemSource obligado a team.members?

Normalmente, estoy asignando mi datacontext en mi código, pero aún así no debería ser diferente para usted.

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

supongo que realmente es la misma cosa como lo sugirió Aviad. Sólo me asigne DataContext en mi código subyacente.

Cuestiones relacionadas