【问题标题】:TreeView Sync to SelectedItem in View ModelTreeView 同步到视图模型中的 SelectedItem
【发布时间】:2010-12-15 23:06:05
【问题描述】:

我在 WPF TreeView 控件之上有一个 ViewModel。我希望 ViewModel 能够从 TreeView 设置和读取 SelectedItem。但是,TreeView 的 SelectedItem 属性不可绑定。

我能够在后面的代码中设置和获取选定的项目(使用 ItemContainerGenerator 和 TreeViewItem.IsSelected = true),但这会导致后面的代码和 ViewModel 之间的通信出现一些丑陋的情况。

有人对此有干净的解决方案吗?

【问题讨论】:

标签: wpf treeview viewmodel selecteditem


【解决方案1】:

我可以举个例子。 我所做的是在视图模型中设置TreeViewItemIsSelected 属性(不是TreeView 本身),因为您可以绑定到它。

在我的视图模型中,我有一个属性ElementInViewModel,它是一个自身形成树的数据结构。 我在 Xaml 中使用 HierarchicalDataTemplate 来显示它。 数据对象本身的类型为YourDomainType,其子元素(相同类型)在其ChildElements 属性中。

在视图模型中,我设置了我的数据类YourDomainTypeIsExpandedIsSelected 属性。由于下面定义的样式,他们会将此设置传递给TreeViewItem

这对你有用吗?

<UserControl>

    <UserControl.Resources>        
        <CollectionViewSource Source="{Binding Path=ElementInViewModel}" x:Key="Cvs">
        </CollectionViewSource>

        <HierarchicalDataTemplate DataType="{x:Type DomainModel:YourDomainType}"
                                  ItemsSource="{Binding Path=ChildElements}">
            <TextBlock Text="{Binding Path=Name}"/>            
        </HierarchicalDataTemplate>        

        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            </Setter>
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            </Setter>            
        </Style>

    </UserControl.Resources>


    <DockPanel>
        <TreeView ItemsSource="{Binding Source={StaticResource Cvs}}"/>
    </DockPanel>

</UserControl>

【讨论】:

    【解决方案2】:

    您可以使用某种代理类将 SelectedItem 属性绑定到 In 属性,并将 Out 属性绑定到您的 ViewModel:

        public class Proxy : FrameworkElement
        {
        public static readonly DependencyProperty InProperty;
        public static readonly DependencyProperty OutProperty;
    
        public Proxy()
        {
            Visibility = Visibility.Collapsed;
        }
    
        static Proxy()
        {
            var inMetadata = new FrameworkPropertyMetadata(
                delegate(DependencyObject p, DependencyPropertyChangedEventArgs args)
                    {
                        if (null != BindingOperations.GetBinding(p, OutProperty))
                        {
                            var proxy = p as Proxy;
                            if (proxy != null)
                                proxy.Out = args.NewValue;
                        }
                    });
    
            inMetadata.BindsTwoWayByDefault = false;
            inMetadata.DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    
            InProperty = DependencyProperty.Register("In",
                                                     typeof (object),
                                                     typeof (Proxy),
                                                     inMetadata);
    
            var outMetadata = new FrameworkPropertyMetadata(
                delegate(DependencyObject p, DependencyPropertyChangedEventArgs args)
                    {
                        ValueSource source = DependencyPropertyHelper.GetValueSource(p, args.Property);
    
                        if (source.BaseValueSource != BaseValueSource.Local)
                        {
                            var proxy = p as Proxy;
                            if (proxy != null)
                            {
                                var expected = proxy.In;
                                if (!ReferenceEquals(args.NewValue, expected))
                                {
                                    Dispatcher.CurrentDispatcher.BeginInvoke(
                                        DispatcherPriority.DataBind, new Action(delegate
                                                                                    {
                                                                                        proxy.Out = proxy.In;
                                                                                    }));
                                }
                            }
                        }
                    });
    
            outMetadata.BindsTwoWayByDefault = true;
            outMetadata.DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    
            OutProperty = DependencyProperty.Register("Out",
                                                      typeof (object),
                                                      typeof (Proxy),
                                                      outMetadata);
        }
    
        public object In
        {
            get { return GetValue(InProperty); }
            set { SetValue(InProperty, value); }
        }
    
        public object Out
        {
            get { return GetValue(OutProperty); }
            set { SetValue(OutProperty, value); }
        }
    }
    <Proxy In="{Binding ElementName=Tree, Path=SelectedItem}" Out="{Binding SelectedItem, UpdateSourceTrigger=PropertyChanged}"/>
    <TreeView x:Name="Tree" ItemsSource="{Binding Path=Items}"/>
    

    【讨论】:

      猜你喜欢
      • 2012-11-26
      • 2016-11-30
      • 2011-06-06
      • 2012-03-17
      • 1970-01-01
      • 2018-05-25
      • 2012-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多