Jak mogę pobrać element wybrany w widoku drzewa WPF? Chcę to zrobić w XAML, ponieważ chcę to powiązać.
Możesz pomyśleć, że tak, SelectedItem
ale najwyraźniej nie istnieje, jest tylko do odczytu i dlatego nie nadaje się do użytku.
Oto co chcę zrobić:
<TreeView ItemsSource="{Binding Path=Model.Clusters}"
ItemTemplate="{StaticResource ClusterTemplate}"
SelectedItem="{Binding Path=Model.SelectedCluster}" />
Chcę powiązać SelectedItem
właściwość z moim modelem.
Ale to daje mi błąd:
Właściwość „SelectedItem” jest tylko do odczytu i nie można jej ustawić na podstawie znaczników.
Edycja: Ok, oto jak to rozwiązałem:
<TreeView
ItemsSource="{Binding Path=Model.Clusters}"
ItemTemplate="{StaticResource HoofdCLusterTemplate}"
SelectedItemChanged="TreeView_OnSelectedItemChanged" />
oraz w pliku codebehindfile mojego xaml:
private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
Model.SelectedCluster = (Cluster)e.NewValue;
}
Odpowiedzi:
Zdaję sobie sprawę, że odpowiedź została już zaakceptowana, ale zebrałem ją, aby rozwiązać problem. Wykorzystuje podobny pomysł do rozwiązania Delta, ale bez potrzeby podklasy TreeView:
Następnie możesz użyć tego w swojej XAML jako:
Mam nadzieję, że to komuś pomoże!
źródło
{Binding SelectedItem, Mode=TwoWay}
z{Binding MyViewModelField, Mode=TwoWay}
xmlns:e="http://schemas.microsoft.com/expression/2010/interactivity"
Ta właściwość istnieje: TreeView.SelectedItem
Ale jest tylko do odczytu, więc nie można przypisać go przez powiązanie, a jedynie pobrać
źródło
TreeView.SelectedItem
wpłynąć na właściwość modelu, gdy użytkownik wybierze element (aliasOneWayToSource
)?Odpowiedz z dołączonymi właściwościami i bez zewnętrznych zależności, jeśli zajdzie taka potrzeba!
Możesz utworzyć dołączoną właściwość, którą można powiązać i która zawiera getter i setter:
Dodaj deklarację przestrzeni nazw zawierającą tę klasę do swojej XAML i powiąż w następujący sposób (lokalny to sposób, w jaki nazwałem deklarację przestrzeni nazw):
Teraz możesz powiązać wybrany element, a także ustawić go w modelu widoku, aby zmienić go programowo, jeśli kiedykolwiek pojawi się to wymaganie. Zakłada się oczywiście, że zaimplementujesz INotifyPropertyChanged dla tej konkretnej właściwości.
źródło
Cóż, znalazłem rozwiązanie. Porusza bałagan, dzięki czemu MVVM działa.
Najpierw dodaj tę klasę:
i dodaj to do swojego xaml:
źródło
Odpowiada nieco więcej, niż się spodziewa PO ... Ale mam nadzieję, że to może komuś pomóc.
Jeśli chcesz wykonać
ICommand
, gdySelectedItem
zmianie, można powiązać komendę na zdarzenia i wykorzystania nieruchomościSelectedItem
wViewModel
nie jest już potrzebny.Aby to zrobić:
1- Dodaj odniesienie do
System.Windows.Interactivity
2- Powiąż polecenie z wydarzeniem
SelectedItemChanged
źródło
System.Windows.Interactivity
można zainstalować z NuGet: nuget.org/packages/System.Windows.Interactivity.WPFSystem.Windows.Interactivity
. To zadziałało dla mnie (próbowałem z projektem .NET Core). Aby to skonfigurować, po prostu dodaj pakiet nuget Microsoft.Xaml.Behaviors.Wpf , zmień przestrzeń nazw naxmlns:i="http://schemas.microsoft.com/xaml/behaviors"
. Aby uzyskać więcej informacji - zobacz blogMożna to osiągnąć w „ładniejszy” sposób, używając tylko wiązania i EventToCommand biblioteki GalaSoft MVVM Light. Na maszynie wirtualnej dodaj polecenie, które zostanie wywołane, gdy wybrany element zostanie zmieniony, i zainicjuj polecenie, aby wykonać niezbędne czynności. W tym przykładzie użyłem RelayCommand i po prostu ustawię właściwość SelectedCluster.
Następnie dodaj zachowanie EventToCommand do twojego xaml. Jest to naprawdę łatwe przy użyciu mieszanki.
źródło
Wszystko skomplikowane ... Przejdź z Caliburn Micro (http://caliburnmicro.codeplex.com/)
Widok:
ViewModel:
źródło
Natknąłem się na tę stronę, szukając tej samej odpowiedzi, co autor, i udowadniając, że zawsze jest na to więcej niż jeden sposób, rozwiązanie było dla mnie jeszcze łatwiejsze niż odpowiedzi tutaj podane, więc pomyślałem, że równie dobrze mogę dodać na stos.
Motywacją do wiązania jest utrzymanie go w porządku i MVVM. Prawdopodobne użycie ViewModel to posiadanie właściwości o nazwie takiej jak „CurrentThingy”, a gdzie indziej DataContext w innej rzeczy jest powiązany z „CurrentThingy”.
Zamiast przejść dodatkowe kroki wymagane (np .: niestandardowe zachowanie, kontrola innej firmy) w celu obsługi ładnego powiązania z TreeView z moim modelem, a następnie z czegoś innego do mojego modelu, moim rozwiązaniem było użycie prostego elementu wiążącego inną rzecz z TreeView.SelectedItem, zamiast wiązania innej rzeczy z moim ViewModel, pomijając w ten sposób dodatkową wymaganą pracę.
XAML:
Oczywiście, jest to świetne do czytania aktualnie wybranego elementu, ale bez ustawiania go, co jest wszystkim, czego potrzebowałem.
źródło
Może być również możliwe użycie właściwości TreeViewItem.IsSelected
źródło
Istnieje również sposób na utworzenie powiązanej z XAML właściwości SelectedItem bez użycia Interaction.Behaviors.
Następnie możesz użyć tego w swojej XAML jako:
źródło
Próbowałem wszystkich rozwiązań tych pytań. Nikt nie rozwiązał w pełni mojego problemu. Myślę więc, że lepiej użyć takiej odziedziczonej klasy z przedefiniowaną właściwością SelectedItem. Będzie działał idealnie, jeśli wybierzesz element drzewa z GUI i ustawisz tę wartość właściwości w swoim kodzie
źródło
Moje wymaganie dotyczyło rozwiązania opartego na PRISM-MVVM, w którym potrzebny był TreeView, a związany obiekt jest typu Collection <>, a zatem potrzebuje HierarchicalDataTemplate. Domyślny BindableSelectedItemBehavior nie będzie w stanie zidentyfikować potomnego TreeViewItem. Aby działało w tym scenariuszu.
Umożliwia to iterację wszystkich elementów niezależnie od poziomu.
źródło
Sugeruję uzupełnienie zachowania zapewnionego przez Steve'a Greatrexa. Jego zachowanie nie odzwierciedla zmian ze źródła, ponieważ może nie być zbiorem TreeViewItems. Jest więc kwestią znalezienia TreeViewItem w drzewie, którego tekstem danych jest selectedValue ze źródła. TreeView ma chronioną właściwość o nazwie „ItemsHost”, która przechowuje kolekcję TreeViewItem. Możemy to zrobić przez odbicie i przejść się po drzewie w poszukiwaniu wybranego elementu.
W ten sposób zachowanie działa w przypadku powiązań dwukierunkowych. Alternatywnie możliwe jest przeniesienie akwizycji ItemsHost do metody OnAttached Behaviour, co pozwala zaoszczędzić na nakładach związanych z odbiciem przy każdej aktualizacji wiązania.
źródło
WPF MVVM TreeView SelectedItem
... jest lepszą odpowiedzią, ale nie wspomina o sposobie uzyskania / ustawienia SelectedItem w ViewModel.
źródło
Po studiach przez jeden dzień w Internecie znalazłem własne rozwiązanie do wyboru elementu po utworzeniu normalnego widoku drzewa w normalnym środowisku WPF / C #
źródło
Można to również zrobić za pomocą właściwości IsSelected elementu TreeView. Oto jak to zrobiłem,
Następnie w ViewModel, który zawiera dane, z którymi związany jest Twój TreeView, po prostu subskrybuj zdarzenie w klasie TreeViewItem.
Na koniec zaimplementuj ten moduł obsługi w tym samym ViewModel,
I oczywiście wiązanie
źródło
Wiem, że ten wątek ma 10 lat, ale problem nadal istnieje ....
Pierwotne pytanie brzmiało „odzyskać” wybrany element. Musiałem także „uzyskać” wybrany element w moim viewmodelu (nie ustawiać go). Spośród wszystkich odpowiedzi w tym wątku, odpowiedź „Wesa” jest jedyną, która podchodzi do problemu inaczej: Jeśli możesz użyć „Selected Item” jako celu do wiązania danych, użyj go jako źródła do wiązania danych. Wes zrobił to z inną właściwością view, zrobię to z właściwością viewmodel:
Potrzebujemy dwóch rzeczy:
Viewmodel:
Wyświetl konstruktora:
źródło
(Po prostu wszyscy zgódźmy się, że TreeView jest oczywiście zablokowany w związku z tym problemem. Powiązanie z SelectedItem byłoby oczywiste. Westchnienie )
Potrzebowałem rozwiązania, aby poprawnie współpracować z właściwością IsSelected TreeViewItem, więc oto jak to zrobiłem:
Z tym XAML:
źródło
Przedstawiam wam moje rozwiązanie, które oferuje następujące funkcje:
Obsługuje 2 sposoby wiązania
Automatycznie aktualizuje właściwości TreeViewItem.IsSelected (zgodnie z SelectedItem)
Brak podklasy TreeView
Elementy powiązane z ViewModel mogą być dowolnego typu (nawet zerowe)
1 / Wklej następujący kod w swoim CS:
2 / Przykład użycia w pliku XAML
źródło
Proponuję to rozwiązanie (które uważam za najłatwiejsze i wolne od wycieków pamięci), które działa idealnie do aktualizacji wybranego elementu ViewModel z wybranego elementu View.
Należy pamiętać, że zmiana wybranego elementu z ViewModel nie spowoduje aktualizacji wybranego elementu w View.
Wykorzystanie XAML
źródło