【问题标题】:Get TreeView SelectedItem inside ViewModel在 ViewModel 中获取 TreeView SelectedItem
【发布时间】:2017-09-07 15:22:26
【问题描述】:

我正在尝试在 ViewModel 中选择 TreeView 节点

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>

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");
            }
        }       
    }

最后是数据类

[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;

                }
            }
        }
    }

当 Treeview 节点被选中时,IsSelected 在 GroupTable 或 StaticTablesGroup 中引发。 如何在 TreeTablesViewModel 中获取选定节点?

谢谢

【问题讨论】:

    标签: c# wpf xaml mvvm treeview


    【解决方案1】:

    您不应尝试在视图模型中操作视图对象(TreeView、TreeViewItem、TreeNode 等)。您的视图模型必须只操作业务/poco 对象。

    如果要检索与所选可视对象(TreeViewItem 或节点)对应的底层业务对象,可以使用如下行为:

    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;
    
        }
    }
    

    TreeView.SelectedItem 直接返回与 Selected TreeviewItem 关联的业务对象。

    在 xaml 中,使用附加属性将 SelectedItemHolder 绑定到您的视图模型

    <TreeView ItemsSource="{Binding TreeViewModel.TreeData}" local:TreeviewSelectedItemTracker.SelectedItemHolder="{Binding}"/>
    

    【讨论】:

    • 感谢您的回复。我将 Selecteditem 属性添加到 TreeTablesViewModel: private object _selectedItem;公共对象 SelectedItem { 获取 { 返回 _selectedItem; } 设置 { _selectedItem = 值; OnPropertyChanged("SelectedItem");但是,viewModel 中的 SelectedItem 永远不会被执行。我做错了什么。
    • 在 XAML 中:
    • 您是否尝试在行为中的 SelectedItemChanged 处理程序中放置一个断点以查看是否引发了事件?
    • Tv_SelectedItemChanged 事件永远不会引发
    • 这意味着绑定到“SelectedItemHolder”属性没有绑定到正确的对象。绑定不能指向 SelectedItemProperty 本身,而是视图模型: vm:TreeviewSelectedItemTracker.SelectedItemHolder="{Binding TreeViewModel}
    【解决方案2】:

    获取 TreeViewItem(我认为您的意思)的最简单方法是从树的选择处理程序中的项目容器生成器中获取它。

        private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            TreeView tv = e.Source as TreeView;
            TreeViewItem tvi = tv.ItemContainerGenerator.ContainerFromItem(e.NewValue) as TreeViewItem;
        }
    

    XAML

        <TreeView ItemsSource="{Binding TreeViewModel.TreeData}" SelectedItemChanged="treeView_SelectedItemChanged" >
    

    我想你可以从这里进入视图模型。

    【讨论】:

    • 我正在尝试不使用 MVVM 模式添加代码
    猜你喜欢
    • 2010-11-17
    • 1970-01-01
    • 2015-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    • 2012-03-17
    相关资源
    最近更新 更多