WPF DataGridTemplateColumn mit ComboBox-Binding - (MVVM-pattern)
Werde ich verrückt mit den folgenden WPF-DataGrid+ComboBox-Szenario.
Habe ich eine Reihe von Klassen, die so Aussehen;
class Owner
{
int ID { get; }
string Name { get; }
public override ToString()
{
return this.Name;
}
}
class House
{
int ID { get; }
Owner HouseOwner { get; set; }
}
class ViewModel
{
ObservableCollection<Owner> Owners;
ObservableCollection<House> Houses
}
Nun meine gewünschte Ergebnis ist ein DataGrid, die zeigt eine Liste der Zeilen des Typs Haus, und in einer der Spalten, ist ein Auswahlfeld, in das der Benutzer ändern Sie den Wert von Haus.Vermieter.
In diesem Szenario wird der DataContext für das raster ist ViewModel.Häuser und für die ComboBox, ich will, dass die ItemsSource gebunden zu sein, zum ViewModel.Besitzer.
Ist das überhaupt möglich? Ich werde mental mit diesem... die besten, die ich in der Lage gewesen zu tun ist, um richtig zu Holen die ItemsSource gebunden, aber das Kombinationsfeld (in einem DataGridTemplateColumn) zeigt nicht die richtigen Werte für das Haus.Vermieter in jeder Zeile.
HINWEIS: Wenn ich die ComboBox aus dem Bild heraus und setzen Sie einen TextBlock in der DataTemplate statt, ich kann richtig sehen, wie die Werte für jede Zeile, die aber immer sowohl eine ItemsSource-als auch den richtigen Wert bei der Auswahl ist nicht für mich arbeiten...
In meinem code, ich habe den DataContext auf das Fenster zu ViewModel und auf dem Gitter, den DataContext gesetzt ist ViewModel.Häuser. Für alles außer dieses Kombinationsfeld, das es funktioniert...
Meiner XAML-Code für die problematische Spalte aussieht;
<DataGridTemplateColumn Header="HouseOwner">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=DataContext.Owners, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
DisplayMemberPath="Name"
SelectedItem="{Binding HouseOwner, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
SelectedValue="{Binding HouseOwner.ID, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Mode=OneWay}"
SelectedValuePath="ID" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Würde gerne etwas Hilfe dabei... scheint wie ein bisschen Voodoo ist erforderlich, wenn...
InformationsquelleAutor RJ Lohan | 2011-08-17
Du musst angemeldet sein, um einen Kommentar abzugeben.
als Standard.kramer sagte, müssen Sie zum entfernen der
RelativeSource
aus Ihrem Bindungen für dieSelectedItem
undSelectedValue
wie folgt aus (beachten Sie, dass sollten SieMode=TwoWay
zu Ihrer Bindung, so daß die änderung in der combobox spiegelt sich in Ihrem Modell).Jedoch, im Gegensatz, sagte er, Sie don ' T haben, entfernen Sie die Bindung für die
SelectedValue
. In der Tat, wenn Sie es entfernen, wird es nicht funktionieren (beideSelectedValue
undSelectedValuePath
sollte hier eingestellt werden, wie Sie getan haben), weil das, was ermöglichen es, den Mechanismus für die Bindung zu identifizieren, die die Auswahl aus der combobox der DataGrid -HouseOwner
Eigenschaft.SelectedValue
/SelectedValuePath
Kombination ist sehr interessant.SelectedValuePath
sagt das databinding, dass dieID
Eigenschaft desOwner
Objekt gerade ausgewählt vertritt seine Wert,SelectedValue
sagt, dass es das Wert gebunden werden soll, dieHouseOwner.ID
die das ausgewählte Objekt an die DataGrid.Daher, wenn Sie entfernen diese Bindung, die einzige Sache, die databinding-Mechanismus kennen, "was für ein Objekt ist selektiert", um die Korrespondenz zwischen dem ausgewählten Element in der ComboBox und der
HouseOwner
Eigenschaft für das ausgewählte Element im DataGrid, Sie müssen "die gleiche Objekt-Referenz". Das bedeutet, dass zum Beispiel das folgende würde nicht funktionieren:(beachten Sie, dass die "HouseOwners" der Häuser-Sammlung sind verschiedene (neue) von denen, die in der Eigentümer-Sammlung). Jedoch, die folgenden würde Arbeit:
Hoffe, das hilft 🙂
Update: im zweiten Fall können Sie das gleiche Ergebnis erhalten, ohne dass die Referenzen, die gleichen durch das überschreiben Gleich auf die
Owner
Klasse (natürlich, da es verwendet, vergleichen Sie die Objekte in den ersten Platz). (Dank an @RJ Lohan zum notieren diese in die Kommentare unten)Ehrlich gesagt, ich dachte auch, dass das problem war, bis ich es selbst ausprobiert 🙂
Danke für die Antwort, aber das ist noch nicht so ganz, für mich zu arbeiten. Ich habe die XAML-binding-setup nur-wie Sie anmerken -, mit einer ändern - weil Besitzer.ID hat nur eine get-Methode, habe ich die SelectedValue-Bindung auf OneWay, während Sie die SelectedItem-Bindung ist festgelegt als TwoWay (sonst bekomme ich runtime-exceptions). Auch ich dachte, die TwoWay-Bindung war die Vorgabe, so würde kein müssen angegeben werden, auf die SelectedItem? Jedenfalls noch nicht für mich arbeiten - ich bin immer noch nicht in der Lage zu ändern die Auswahl in der ComboBox...
Ein anderer Gedanke; RE: "um die Korrespondenz zwischen dem ausgewählten Element in der ComboBox und der Vermieter-Eigenschaft für das ausgewählte Element im DataGrid, so haben Sie als "das gleiche Objekt Referenz"... habe ich überschrieben mit der Gleich - Methode in mein Besitzer-Objekt (in den real-code) gleichzusetzen, auf ID, so dass ich dachte, dass der Wert-Bindungen überflüssig werden, als die SelectedItem binden könnte, vergleichen Sie verschiedene Instanzen der Besitzer, wo die IDs gleich sind. Übrigens, ich habe es geschafft, diese Arbeit in die code-behind-mit einem DataGridComboBoxColumn... der XAML-Ansatz noch entzieht sich mir
Der Standard-Modus für die Bindung ist OneWay, und dann zu vergessen, stellen Sie es auf TwoWay gab mir eine Menge Kopfschmerzen. Für Ihre Bemerkung auf das "selbe Objekt verweisen", du hast Recht. Ich habe gerade versucht es aus, und überschreiben Sie die Gleich funktioniert (das ist zu erwarten, denn das ist die Methode, die verwendet wird, um zu überprüfen, die Geschlechter, und standardmäßig prüft es, ob es das "gleiche Referenz" 😉 ). Froh, irgendwie zu helfen 🙂
InformationsquelleAutor AbdouMoumen
Danke für die Hilfe, habe ich endlich rausgefunden, warum ich konnte nicht wählen Sie die ComboBox-Einträge - wurde durch einen Maus-preview-event-handler, die ich angeschlossen hatte, um die Formatvorlage für die Zelle, wenn ich mit einem DataGridComboBoxColumn.
Habe mich selbst geohrfeigt für diesen einen danke für die sonstige Hilfe.
Auch als ein Hinweis; der einzige Weg, das funktioniert für mich mit einem zusätzlichen;
Hinzugefügt, um die ComboBox, aber Sie alle zeigen den gleichen Wert aus irgendeinem Grund.
Außerdem habe ich nicht erscheinen, zu verlangen, dass der SelectedValue/SelectedValuePath Eigenschaften in meine Bindung, ich glaube, da habe ich überschrieben Gleich in meine gefesselten Eigentümer geben.
Und zu guter Letzt, habe ich explizit festgelegt;
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged
In der Bindung, um für die Werte geschrieben werden, zurück an die gebundenen Elemente bei der ComboBox geändert hat.
So, die letzten (Arbeits -) XAML-Code für das binding sieht wie folgt aus;
Prost!
rJ
InformationsquelleAutor RJ Lohan
Dies ist auf jeden Fall möglich und du bist auf dem richtigen Weg mit einem
AncestorType
verbindlich für dieItemsSource
. Aber ich glaube, ich sehe ein paar Fehler.Zuerst, Ihre
ItemsSource
verbindlich sein sollte, umDataContext.Owners
, nichtDataContext.Houses
, richtig? Sie möchten die viewmodels' - Kollektion von Eigentümern zu zeigen, bis in der drop-down-Menü. So ändern Sie zunächst dieItemsSource
und nehmen Sie die Auswahl-bezogene Sachen, wie z.B. dieser:Nun testen Sie es aus und stellen Sie sicher, dass die
ItemsSource
richtig funktioniert. Versuchen Sie nicht, Herumspielen mit Auswahl, bis das Teil funktioniert.Zur Auswahl, ich denke, Sie sollten verbindlich
SelectedItem
nur - nichtSelectedValue
. Für diese bindend werden, nicht wollen eineRelativeSource
Bindung - das DataContext eine einzelneHouse
so können Sie binden direkt seineHouseOwner
. Meine Vermutung ist diese:Schließlich für debugging-Bindungen können Sie siehe Ausgabefenster von Visual Studio oder Schritt bis zu einem tool wie Snoop oder WPF Inspector. Wenn Sie planen, tun eine Menge von WPF, würde ich empfehlen, erste Schritte mit Snoop früher als später.
Habe ich fummelte mit meinen code ein wenig, und jetzt habe ich traf eine etwas andere Haken. Mit dem code umgesetzt, wie Sie haben, mit nur SelectedItem gebunden, alle Zeilen zeigen den gleichen Wert für Vermieter... keine Ahnung, was das bedeutet, aber es scheint, Sie sind nicht richtig gebunden. Beim googeln stieß ich auf einen anderen Vorschlag, wo ich Hinzugefügt haben; IsSynchronizedWithCurrentItem="False" in meiner ComboBox. Dies führte dazu, dass die richtigen Werte angezeigt, die für jedes Element und die richtigen Entscheidungen in der dropdown... aber jetzt bin ich nicht in der Lage zu ändern mit der Auswahl!
InformationsquelleAutor default.kramer
Komplette Beispiel basiert auf AbdouMoumen Vorschlag. Auch entfernt SelectedValue & SelectedValuePath.
InformationsquelleAutor rr789