TreeView 同步到视图模型中的 SelectedItem
Posted
技术标签:
【中文标题】TreeView 同步到视图模型中的 SelectedItem【英文标题】:TreeView Sync to SelectedItem in View Model 【发布时间】:2010-12-15 23:06:05 【问题描述】:我在 WPF TreeView 控件之上有一个 ViewModel。我希望 ViewModel 能够从 TreeView 设置和读取 SelectedItem。但是,TreeView 的 SelectedItem 属性不可绑定。
我能够在后面的代码中设置和获取选定的项目(使用 ItemContainerGenerator 和 TreeViewItem.IsSelected = true),但这会导致后面的代码和 ViewModel 之间的通信出现一些丑陋的情况。
有人对此有干净的解决方案吗?
【问题讨论】:
你解决过这个问题吗?我正好有这个问题。 我认为这个问题与***.com/questions/1000040/…重复 【参考方案1】:我可以举个例子。
我所做的是在视图模型中设置TreeViewItem
的IsSelected
属性(不是TreeView
本身),因为您可以绑定到它。
在我的视图模型中,我有一个属性ElementInViewModel
,它是一个自身形成树的数据结构。
我在 Xaml 中使用 HierarchicalDataTemplate
来显示它。
数据对象本身的类型为YourDomainType
,其子元素(相同类型)在其ChildElements
属性中。
在视图模型中,我设置了我的数据类YourDomainType
的IsExpanded
和IsSelected
属性。由于下面定义的样式,他们会将此设置传递给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"/>
【讨论】:
以上是关于TreeView 同步到视图模型中的 SelectedItem的主要内容,如果未能解决你的问题,请参考以下文章