2009-12-24 9 views
7

ho una finestra WPF con un modello di vista posta come DataContext, e hanno un ListBox con un DataTemplate e la sua ItemsSource legato al modello di vista, come nel seguente esempio:In WPF, come eseguire il databind su Window DataContext dall'interno del DataTemplate di un ListBox contenuto?

vista del modello:

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> 

Naturalmente, la proprietà TeamName della classe squadra non è visualizzata in elementi ListBox perché ogni elemento della LisBox è il DataContext del List.ItemTemplate, e sostituisce t lui DataContext della finestra.

La domanda è: come si associa la proprietà TeamName del modello di visualizzazione (Window.DataContext) all'interno del DataTemplate di ListBox?

risposta

12

vorrei estrarre il l: dichiarazione di squadra alla sezione Window.Resources, e farvi riferimento dall'interno del DataContext e 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. Certo! Non avevo pensato di condividere il modello di visualizzazione come una risorsa, stavo cercando di complicare le relazioni con RelativeSources e FindAncestor senza successo –

+0

Oops, ti voterei se avessi abbastanza reputazione –

1

mi piacerebbe creare un modello di vista per un membro del team, con un TeamName proprietà, qualcosa di simile a:

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

Allora il tuo XAML avrà un aspetto più pulito nel tuo esempio. Con MVVM, non dovresti aver bisogno di trucchi vincolanti nella vista. Tutto ciò che serve dovrebbe essere disponibile tramite il modello di visualizzazione.

+1

E come dovrei fare i databindings ? –

14

È inoltre possibile utilizzare vincolante RelativeSource, non è così complicato:

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

Perché non si associa il vostro DataContext alla squadra, poi fatevi ItemSource destinata a team.members?

di solito sto assegnando il mio datacontext nel mio codebehind ma non dovrebbe essere per nulla diverso da te.

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

Credo davvero sua la stessa cosa di ciò che Aviad suggerito. Proprio assegno DataContext nel mio codebehind.

Problemi correlati