2009-12-24 7 views
7

Ich habe ein WPF-Fenster mit Blick Modell als Datacontext gesetzt und habe eine List-Box mit einem Datatemplate und seine Itemssource an das View-Modell gebunden, wie im folgende Beispiel:Wie kann in WPF von der DataTemplate einer enthaltenen ListBox in den Window DataContext eingebunden werden?

anzeigen Modell:

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> 

natürlich ist der Teamname-Eigenschaft des Teams Klasse nicht in der List-Box Artikel angezeigt werden, weil jedes Element des LisBox die Datacontext des List.ItemTemplate ist, und es überschreibt t Der DataContext des Fensters.

Die Frage ist: Wie kann ich mit der TeamName-Eigenschaft des Ansichtsmodells (Window.DataContext) aus der ListTo DataTemplate?

Antwort

12

ich die l extrahieren würde: Team Erklärung an dem Window.Resources Abschnitt, und es aus dem Datacontext und die Datatemplate Referenz:

<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. Natürlich! Ich hatte nicht daran gedacht, das Ansichtsmodell als Ressource zu verwenden. Ich versuchte, die Messungen mit RelativeSources und FindAncestor ohne Erfolg zu verkomplizieren. –

+0

Hoppla, ich würde dich wählen, wenn ich genug Reputation hätte. –

1

ich einen Blick Modell für ein Teammitglied schaffen würde, mit ein TeamName Eigenschaft, so etwas wie:

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

Dann XAML wird wie in Ihrem Beispiel so sauber aussehen. Mit MVVM sollten Sie keine exotischen Bindetricks in der Ansicht benötigen. Alles, was Sie brauchen, sollte über das Ansichtsmodell verfügbar sein.

+1

Und wie würde ich die Datenbindungen machen ? –

14

Sie können auch verwenden Relative Bindung, dann ist es nicht so kompliziert:

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

Warum Team nicht Sie binden Ihre Datacontext, dann ItemSource zu team.members gebunden machen?

In der Regel gebe ich meinen Datenkontext in meinen Code zurück, aber es sollte immer noch nicht anders für Sie sein.

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

ich seine denke, die gleiche Sache wirklich so etwas Aviad vorgeschlagen. Nur ich Datacontext in meinem Code-Behind zuweisen.

Verwandte Themen