2017-10-27 1 views
-2

Wenn das Hauptfenster - nur meine DataGrid zeigt, zeigt die DataGrid null Zeilen. DieseWarum zeigt mein DataGrid keine Zeilen an, wenn Elemente in der gebundenen Datenquelle enthalten sind?

ist, was mein Gitter aussieht:

<DataGrid     
     AutoGenerateColumns="True" 
     CanUserAddRows="False" 
     CanUserReorderColumns="True" 
     CanUserResizeColumns="True" 
     DataContext="ClientListViewModel" 
     ItemsSource="{Binding Source=RowItems}"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Given Name" Binding="{Binding GivenName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
     <DataGridTextColumn Header="Family Name" Binding="{Binding FamilyName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
     <DataGridTextColumn Header="Gender" Binding="{Binding Gender, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
     <DataGridTextColumn Header="Date of Birth" Binding="{Binding DateOfBirth, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
    </DataGrid.Columns> 
</DataGrid> 

Im Source={Binding Source=RowItems} die Quelle eine Eigenschaft ist, RowItems auf meinem Haupt-View-Modell, ClientListViewModel.

Das Viewmodel hat eine Read Methode in der Ctor ClientListView, meine Hauptansicht genannt. Wenn ich dieses Problem debuggen kann, kann ich sehen, dass die Artikelquelle RowItems korrekt ausgefüllt ist.

Meine Initialisierung der Hauptansicht, die UserControl die DataGrid in Frage kommenden sieht, wie folgt aus:

public MainWindow() 
{ 
    InitializeComponent(); 
    InitializeListView(); 
} 

private void InitializeListView() 
{ 
    var model = new ClientListViewModel(); 
    model.Read(); 
    var view = new ClientListView(); 
    view.DataContext = model; 
    Content = view; 
} 

Als ich nach model.Read(); gerade einen Haltepunkt setzen, seine model.RowItems Eigenschaft zeigt 12 Artikel, noch die DataGrid Shows keine Zeilen.

Warum ist meine DataGrid rendering null Zeilen?

+4

Wenn Sie '{Binding Source = RowItems}' verwenden, sind Sie nicht an eine 'RowItems' -Eigenschaft des' DataContext' gebunden, aber eher auf das gesamte bindende Quellobjekt, das Sie explizit setzen und in diesem speziellen Fall in eine Zeichenkette "RowItems" aufgelöst wird (beachten Sie, dass es 8 Buchstaben hat). Sie sollten 'Pfad' anstelle von' Quelle' in Ihrer Bindung, d. H. '{Binding Path = RowItems}' oder '{Binding RowItems}' kurz setzen. – Grx70

+0

@ Grx70 Danke, aber ich habe jetzt null Zeilen. Wenn ich Maus über die 'RowItems' in' ItemsSource = "{Binding Path = RowItems}" 'es zeigt mir, dass diese Liste Eigenschaft hat 12 Elemente, noch keine Zeilen! – ProfK

+3

Das liegt daran, dass Sie 'DataGrid.DataContext =" ClientListViewModel "' explizit gesetzt haben, was wiederum zu einem String "ClientListViewModel" 'führt, der keine Eigenschaft namens' RowItems' hat. Wenn Ihr 'DataGrid' Teil Ihrer' ClientListView' ist, können Sie die Einstellung 'DataGrid.DataContext' komplett überspringen (standardmäßig wird es von' ClientListView' geerbt). Andernfalls sollten Sie wahrscheinlich eine korrekte Bindung verwenden, die zu einer Instanz von 'ClientListViewModel' aufgelöst werden würde. Ich empfehle Ihnen, den Artikel [Datenbindungsübersicht] (https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/data-binding-overview) zu besuchen. – Grx70

Antwort

0

Alle Teile sind da, aber sie sind nicht richtig angeordnet. Um DataBinding zu nutzen, müssen Sie einem bestimmten Muster folgen. In diesem Fall sollten Sie diese Schritte ausführen.

public MainWindow() { 
    InitializeComponent(); 
    this.Clients = InitializeListView(); 
    this.DataContext = this;   
} 

public ClientListViewModel Clients { get; set; } 

private ClientListViewModel InitializeListView() { 
    var model = new ClientListViewModel(); 
    model.Read();  
    return model; 
} 

Und MainWindow dar, die nur angedeutet enthält die DataGrid sollte seine ItemSource entsprechend den Eigenschaften des DataContext der Ansicht binden, die in diesem Fall die MainWindow selbst und der DataGrid wird als DataContext

erben
<DataGrid     
     AutoGenerateColumns="False" 
     CanUserAddRows="False" 
     CanUserReorderColumns="True" 
     CanUserResizeColumns="True" 
     ItemsSource="{Binding Clients.RowItems}"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Given Name" Binding="{Binding GivenName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
     <DataGridTextColumn Header="Family Name" Binding="{Binding FamilyName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
     <DataGridTextColumn Header="Gender" Binding="{Binding Gender, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
     <DataGridTextColumn Header="Date of Birth" Binding="{Binding DateOfBirth, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
    </DataGrid.Columns> 
</DataGrid> 
+0

Sie legen 'Clients' nach der Einstellung' DataContext = this' fest und es gibt keine Änderungsbenachrichtigung für diese Eigenschaft, so WPF wird die Änderung nicht bemerken und so keine Daten angezeigt werden. In solchen Fragen sind solche Dinge wichtig. – Evk

+0

@Evk korrekt. Mein Fehler. Aktualisierung jetzt. – Nkosi

+0

Das Setzen einer UI (MainWindow in diesem Fall) als Datenkontext ist wirklich gegen MVVM. Sie können Ihr Ansichtsmodell nicht wiederverwenden/austauschen, ohne die Benutzeroberfläche zu berühren, was einer der größten Vorteile von MVVM ist. – Dominik

0

Sie müssen sicherstellen, dass der Zugriffsmodifizierer Ihrer Bindungsquelle (Klasse) auf public gesetzt ist.

0

Entfernen Source aus der Bindung von ItemsSource in DataGrid und entfernen "ClientListViewModel" von DataContext.

<DataGrid     
     AutoGenerateColumns="True" 
     CanUserAddRows="False" 
     CanUserReorderColumns="True" 
     CanUserResizeColumns="True" 
     ItemsSource="{Binding RowItems}"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Given Name" Binding="{Binding GivenName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
     <DataGridTextColumn Header="Family Name" Binding="{Binding FamilyName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
     <DataGridTextColumn Header="Gender" Binding="{Binding Gender, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
     <DataGridTextColumn Header="Date of Birth" Binding="{Binding DateOfBirth, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> 
    </DataGrid.Columns> 
</DataGrid> 

standardmäßig erben Bindings den Datenkontext von der Datacontext-Eigenschaft angegeben, wenn man festgelegt wurde. Die Source-Eigenschaft ist jedoch eine der Möglichkeiten, die Quelle einer Bindung explizit festzulegen und den geerbten Datenkontext außer Kraft zu setzen. Wenn Sie setzen

ItemsSource="{Binding Source=RowItems}" 

dann RowItems bespannen übersetzt wird (mit Länge 8) und daher sehen Sie acht Zeilen.

+0

@ProfK Ich habe diese Lösung getestet und es sollte funktionieren – user2250152

3
{Binding Source=RowItems} 

bindet nicht an eine Eigenschaft RowItems.

Sie benötigen

{Binding RowItems} 

Auch die Verwendung sicherstellen, dass die Eigenschaft RowItems in Ihrem Ansichtsmodell vom Typ ObservableCollection wie es die Benutzeroberfläche benachrichtigt, dass es Änderungen in der Sammlung, die ein normales List nicht. (Sie benötigen dies, wenn Sie Daten in der Liste ändern, nachdem es gebunden ist)

+1

Um diese Antwort hinzuzufügen (da ich glaube, dass es wahrscheinlich die Lösung ist), lesen Sie [Eigenschaft Änderungsbenachrichtigung] (https: // docs.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-property-change-notification) kann ebenfalls hilfreich sein. –

+0

Ja, das Problem liegt in der Bindung an die RowItems-Eigenschaft. Daher gibt es zwei richtige Antworten. – user2250152

Verwandte Themen