Wie kann ich das in einer WPF-Baumansicht ausgewählte Element abrufen? Ich möchte dies in XAML tun, weil ich es binden möchte.
Sie könnten denken, dass es SelectedItem
aber anscheinend nicht existiert, ist schreibgeschützt und daher unbrauchbar.
Folgendes möchte ich tun:
<TreeView ItemsSource="{Binding Path=Model.Clusters}"
ItemTemplate="{StaticResource ClusterTemplate}"
SelectedItem="{Binding Path=Model.SelectedCluster}" />
Ich möchte das SelectedItem
an eine Eigenschaft in meinem Modell binden .
Aber das gibt mir den Fehler:
Die Eigenschaft 'SelectedItem' ist schreibgeschützt und kann nicht über das Markup festgelegt werden.
Edit: Ok, so habe ich das gelöst:
<TreeView
ItemsSource="{Binding Path=Model.Clusters}"
ItemTemplate="{StaticResource HoofdCLusterTemplate}"
SelectedItemChanged="TreeView_OnSelectedItemChanged" />
und in der codebehindfile meiner xaml:
private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
Model.SelectedCluster = (Cluster)e.NewValue;
}
Antworten:
Mir ist klar, dass dies bereits eine Antwort akzeptiert hat, aber ich habe dies zusammengestellt, um das Problem zu lösen. Es verwendet eine ähnliche Idee wie die Lösung von Delta, ohne dass die TreeView in Unterklassen unterteilt werden muss:
Sie können dies dann in Ihrer XAML verwenden als:
Hoffentlich hilft es jemandem!
quelle
{Binding SelectedItem, Mode=TwoWay}
mit{Binding MyViewModelField, Mode=TwoWay}
xmlns:e="http://schemas.microsoft.com/expression/2010/interactivity"
Diese Eigenschaft ist vorhanden: TreeView.SelectedItem
Es ist jedoch schreibgeschützt, sodass Sie es nicht über eine Bindung zuweisen, sondern nur abrufen können
quelle
TreeView.SelectedItem
auf eine Eigenschaft des Modells auswirken, wenn der Benutzer ein Element (auch bekannt alsOneWayToSource
) auswählt ?Antworten Sie mit angehängten Eigenschaften und ohne externe Abhängigkeiten, falls dies jemals erforderlich sein sollte!
Sie können eine angehängte Eigenschaft erstellen, die bindbar ist und einen Getter und einen Setter enthält:
Fügen Sie die Namespace-Deklaration, die diese Klasse enthält, zu Ihrer XAML hinzu und binden Sie sie wie folgt (lokal habe ich die Namespace-Deklaration benannt):
Jetzt können Sie das ausgewählte Element binden und es in Ihrem Ansichtsmodell so einstellen, dass es programmgesteuert geändert wird, falls diese Anforderung jemals auftritt. Dies setzt natürlich voraus, dass Sie INotifyPropertyChanged für diese bestimmte Eigenschaft implementieren.
quelle
Nun, ich habe eine Lösung gefunden. Es bewegt das Chaos, so dass MVVM funktioniert.
Fügen Sie zuerst diese Klasse hinzu:
und füge dies deinem xaml hinzu:
quelle
Es antwortet etwas mehr als das OP erwartet ... Aber ich hoffe, es könnte zumindest jemandem helfen.
Wenn Sie a ausführen möchten,
ICommand
wann immer diesSelectedItem
geändert wurde, können Sie einen Befehl an ein Ereignis binden, und die Verwendung einer EigenschaftSelectedItem
in derViewModel
wird nicht mehr benötigt.Um dies zu tun:
1- Verweis auf hinzufügen
System.Windows.Interactivity
2- Binden Sie den Befehl an das Ereignis
SelectedItemChanged
quelle
System.Windows.Interactivity
kann von NuGet installiert werden: nuget.org/packages/System.Windows.Interactivity.WPFSystem.Windows.Interactivity
. Es wurde für mich gearbeitet (versucht mit dem .NET Core-Projekt). Um die Dinge einzurichten, fügen Sie einfach das Microsoft.Xaml.Behaviors.Wpf- Nuget-Paket hinzu und ändern Sie den Namespace inxmlns:i="http://schemas.microsoft.com/xaml/behaviors"
. Weitere Informationen finden Sie im BlogDies kann auf eine "schönere" Weise erreicht werden, indem nur die Bindung und der EventToCommand der GalaSoft MVVM Light-Bibliothek verwendet werden. Fügen Sie in Ihrer VM einen Befehl hinzu, der aufgerufen wird, wenn das ausgewählte Element geändert wird, und initialisieren Sie den Befehl, um die erforderlichen Aktionen auszuführen. In diesem Beispiel habe ich einen RelayCommand verwendet und werde nur die SelectedCluster-Eigenschaft festlegen.
Fügen Sie dann das EventToCommand-Verhalten in Ihre xaml ein. Dies ist wirklich einfach mit Blend.
quelle
Alles zu kompliziert ... Gehen Sie mit Caliburn Micro (http://caliburnmicro.codeplex.com/)
Aussicht:
ViewModel:
quelle
Ich bin auf diese Seite gestoßen, um nach der gleichen Antwort wie der ursprüngliche Autor zu suchen, und um zu beweisen, dass es immer mehr als einen Weg gibt, war die Lösung für mich noch einfacher als die Antworten, die hier bisher gegeben wurden, also dachte ich mir, ich könnte sie genauso gut hinzufügen auf den Stapel.
Die Motivation für die Bindung ist es, es schön zu halten & MVVM. Die wahrscheinliche Verwendung des ViewModel besteht darin, eine Eigenschaft mit einem Namen wie "CurrentThingy" zu haben, und an anderer Stelle ist der DataContext für eine andere Sache an "CurrentThingy" gebunden.
Anstatt zusätzliche Schritte durchzuführen (z. B. benutzerdefiniertes Verhalten, Steuerung durch Dritte), um eine nette Bindung von TreeView zu meinem Modell und dann von etwas anderem zu meinem Modell zu unterstützen, bestand meine Lösung darin, eine einfache Elementbindung zu verwenden, an die das andere Ding gebunden wird TreeView.SelectedItem, anstatt das andere Ding an mein ViewModel zu binden, wodurch die zusätzliche Arbeit übersprungen wird.
XAML:
Dies ist natürlich großartig, um das aktuell ausgewählte Element zu lesen, aber nicht einzustellen, was alles ist, was ich brauche.
quelle
Möglicherweise können Sie auch die TreeViewItem.IsSelected-Eigenschaft verwenden
quelle
Es gibt auch eine Möglichkeit, eine XAML-bindbare SelectedItem-Eigenschaft zu erstellen, ohne Interaction.Behaviors zu verwenden.
Sie können dies dann in Ihrer XAML verwenden als:
quelle
Ich habe alle Lösungen dieser Fragen ausprobiert. Niemand hat mein Problem vollständig gelöst. Ich denke, es ist besser, eine solche geerbte Klasse mit der neu definierten Eigenschaft SelectedItem zu verwenden. Es funktioniert perfekt, wenn Sie ein Baumelement aus der GUI auswählen und diesen Eigenschaftswert in Ihrem Code festlegen
quelle
Meine Anforderung war eine PRISM-MVVM-basierte Lösung, bei der eine TreeView benötigt wurde und das gebundene Objekt vom Typ Collection <> ist und daher HierarchicalDataTemplate benötigt. Das Standard-BindableSelectedItemBehavior kann das untergeordnete TreeViewItem nicht identifizieren. Damit es in diesem Szenario funktioniert.
Dies ermöglicht es, alle Elemente unabhängig von der Ebene zu durchlaufen.
quelle
Ich schlage eine Ergänzung zu dem Verhalten von Steve Greatrex vor. Sein Verhalten spiegelt keine Änderungen gegenüber der Quelle wider, da es sich möglicherweise nicht um eine Sammlung von TreeViewItems handelt. Es geht also darum, das TreeViewItem im Baum zu finden, dessen Datenkontext der ausgewählte Wert aus der Quelle ist. Die TreeView verfügt über eine geschützte Eigenschaft namens "ItemsHost", die die TreeViewItem-Auflistung enthält. Wir können es durch Reflexion bekommen und über den Baum nach dem ausgewählten Gegenstand suchen.
Auf diese Weise funktioniert das Verhalten für bidirektionale Bindungen. Alternativ ist es möglich, die ItemsHost-Erfassung in die OnAttached-Methode des Verhaltens zu verschieben, wodurch der Aufwand für die Verwendung von Reflection bei jeder Aktualisierung der Bindung gespart wird.
quelle
WPF MVVM TreeView SelectedItem
... ist eine bessere Antwort, erwähnt jedoch keine Möglichkeit, das SelectedItem im ViewModel abzurufen / festzulegen.
quelle
Nachdem ich einen Tag lang im Internet studiert hatte, fand ich meine eigene Lösung für die Auswahl eines Elements, nachdem ich eine normale Baumansicht in einer normalen WPF / C # -Umgebung erstellt hatte
quelle
Dies kann auch mit der IsSelected-Eigenschaft des TreeView-Elements erfolgen. So habe ich es geschafft:
Abonnieren Sie dann im ViewModel, das die Daten enthält, an die Ihre TreeView gebunden ist, einfach das Ereignis in der TreeViewItem-Klasse.
Implementieren Sie diesen Handler schließlich im selben ViewModel.
Und die Bindung natürlich,
quelle
Ich weiß, dass dieser Thread 10 Jahre alt ist, aber das Problem besteht immer noch ....
Die ursprüngliche Frage lautete "Abrufen" des ausgewählten Elements. Ich musste auch das ausgewählte Element in meinem Ansichtsmodell "abrufen" (nicht festlegen). Von allen Antworten in diesem Thread ist die von 'Wes' die einzige, die das Problem anders angeht: Wenn Sie das 'Ausgewählte Element' als Ziel für die Datenbindung verwenden können, verwenden Sie es als Quelle für die Datenbindung. Wes hat es mit einer anderen view-Eigenschaft gemacht, ich werde es mit einer viewmodel-Eigenschaft machen:
Wir brauchen zwei Dinge:
Ansichtsmodell:
Konstruktor anzeigen:
quelle
(Lassen Sie uns einfach alle zustimmen, dass TreeView in Bezug auf dieses Problem offensichtlich kaputt ist. Die Bindung an SelectedItem wäre offensichtlich gewesen. Seufz )
Ich brauchte die Lösung, um richtig mit der IsSelected-Eigenschaft von TreeViewItem zu interagieren. So habe ich es gemacht:
Mit dieser XAML:
quelle
Ich bringe Ihnen meine Lösung, die folgende Funktionen bietet:
Unterstützt 2 Bindungsmöglichkeiten
Automatische Aktualisierung der TreeViewItem.IsSelected-Eigenschaften (gemäß SelectedItem)
Keine TreeView-Unterklasse
An ViewModel gebundene Elemente können von einem beliebigen Typ sein (sogar null).
1 / Fügen Sie den folgenden Code in Ihr CS ein:
2 / Anwendungsbeispiel in Ihrer XAML-Datei
quelle
Ich schlage diese Lösung vor (die meiner Meinung nach am einfachsten ist und Speicherlecks freisetzt), die perfekt zum Aktualisieren des ausgewählten Elements des ViewModel aus dem ausgewählten Element der Ansicht geeignet ist.
Beachten Sie, dass durch Ändern des ausgewählten Elements im ViewModel das ausgewählte Element der Ansicht nicht aktualisiert wird.
XAML-Nutzung
quelle