Reputation: 113
I'm trying to get selected TreeView Node inside ViewModel
Inside Xaml
<Grid>
<TreeView ItemsSource="{Binding TreeViewModel.TreeData}">
<TreeView.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding GroupTables}" DataType="{x:Type tbl:StaticTablesGroup}">
<Label Content="{Binding Name}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type tbl:GroupTable}">
<Label Content="{Binding Name}"/>
</DataTemplate>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</Grid>
Inside VieModel
public class TreeTablesViewModel : ViewModelBase
{
private TablesXML _tables;
public TreeTablesViewModel()
{
_tables = Deserialize.GuymasterXml();
}
public List<StaticTablesGroup> TreeData
{
get
{
return _tables.StaticTablesGroups;
}
set
{
_tables.StaticTablesGroups = value;
OnPropertyChanged("TreeData");
}
}
}
and finally data classes
[XmlRoot("Tables")]
public class TablesXML
{
public TablesXML()
{
StaticTablesGroups = new List<StaticTablesGroup>();
}
[XmlArray("StaticGroups")]
[XmlArrayItem("StaticGroup", typeof(StaticTablesGroup))]
public List<StaticTablesGroup> StaticTablesGroups { get; set; }
}
public class StaticTablesGroup
{
public StaticTablesGroup()
{
GroupTables = new List<GroupTable>();
}
[XmlAttribute("Name")]
public string Name { get; set; }
//[XmlArray("StaticGroup")]
[XmlElement("Table", typeof(GroupTable))]
public List<GroupTable> GroupTables { get; set; }
}
public class GroupTable
{
[XmlElement("TableName")]
public string Name { get; set; }
[XmlElement("TableTag")]
public string Tag { get; set; }
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
_isSelected = value;
}
}
}
}
When Treeview node is selected then IsSelected raised inside GroupTable or StaticTablesGroup. How can I get selected node inside the TreeTablesViewModel ?
Thank you
Upvotes: 2
Views: 1609
Reputation: 1974
You should not try to manipulate view objects (TreeView, TreeViewItem, TreeNode, etc.) inside your view model. You view model must manipulate only business/poco objects.
If you want to retreive the underlying business object corresponding to the selected visual object (TreeViewItem or node), you can use a behavior like this one :
public class TreeviewSelectedItemTracker
{
public static TreeTablesViewModel GetSelectedItemHolder(DependencyObject obj)
{
return (TreeTablesViewModel)obj.GetValue(SelectedItemHolderProperty);
}
public static void SetSelectedItemHolder(DependencyObject obj, TreeTablesViewModel value)
{
obj.SetValue(SelectedItemHolderProperty, value);
}
public static readonly DependencyProperty SelectedItemHolderProperty =
DependencyProperty.RegisterAttached("SelectedItemHolder", typeof(TreeTablesViewModel), typeof(TreeviewSelectedItemTracker), new PropertyMetadata(null, OnSelectedChanged));
private static void OnSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TreeView tv = (TreeView)d;
tv.Loaded += Tv_Loaded;
}
private static void Tv_Loaded(object sender, RoutedEventArgs e)
{
TreeView tv = (TreeView)sender;
tv.Loaded -= Tv_Loaded;
tv.Unloaded += Tv_Unloaded;
tv.SelectedItemChanged += Tv_SelectedItemChanged;
}
private static void Tv_Unloaded(object sender, RoutedEventArgs e)
{
TreeView tv = (TreeView)sender;
tv.Unloaded -= Tv_Unloaded;
tv.SelectedItemChanged -= Tv_SelectedItemChanged;
}
private static void Tv_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
TreeView tv = (TreeView)sender;
var cotr = GetSelectedItemHolder(tv);
cotr.SelectedItem = tv.SelectedItem;
}
}
The TreeView.SelectedItem
directly returns the business object associated with Selected TreeviewItem
.
In the xaml, use the attached property to bind the SelectedItemHolder
to your view model
<TreeView ItemsSource="{Binding TreeViewModel.TreeData}" local:TreeviewSelectedItemTracker.SelectedItemHolder="{Binding}"/>
Upvotes: 1
Reputation: 5236
The easiest way to get the TreeViewItem (which is what I think you mean) is to get it from the item container generator in the selection handler for the tree.
private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
TreeView tv = e.Source as TreeView;
TreeViewItem tvi = tv.ItemContainerGenerator.ContainerFromItem(e.NewValue) as TreeViewItem;
}
The XAML
<TreeView ItemsSource="{Binding TreeViewModel.TreeData}" SelectedItemChanged="treeView_SelectedItemChanged" >
From here I think you can get to the view model.
Upvotes: 0