如何检索在WPF-treeview中选择的项?我想在XAML中这样做,因为我想绑定它。
您可能认为它是SelectedItem,但显然它不存在是只读的,因此不可用。
这就是我想做的:
<TreeView ItemsSource="{Binding Path=Model.Clusters}"
ItemTemplate="{StaticResource ClusterTemplate}"
SelectedItem="{Binding Path=Model.SelectedCluster}" />
我想将SelectedItem绑定到我的Model上的一个属性。
但这给了我一个错误:
“SelectedItem”属性是只读的,不能从标记中设置。
编辑:
这就是我解决这个问题的方法:
<TreeView
ItemsSource="{Binding Path=Model.Clusters}"
ItemTemplate="{StaticResource HoofdCLusterTemplate}"
SelectedItemChanged="TreeView_OnSelectedItemChanged" />
在我的xaml的代码背后文件:
private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
Model.SelectedCluster = (Cluster)e.NewValue;
}
我偶然发现了这一页,寻找与原作者相同的答案,并证明了总是有不止一种方法来做这件事,解决方案对我来说甚至比这里提供的答案更容易,所以我想我不妨添加到堆中。
绑定的动机是保持良好& MVVM。ViewModel的可能用法是有一个带有名称的属性,例如“CurrentThingy”,而在其他地方,其他东西上的DataContext被绑定到“CurrentThingy”。
而不是通过额外的步骤(例如:自定义行为,第三方控制)来支持从TreeView到我的模型的良好绑定,然后从其他东西到我的模型,我的解决方案是使用简单的元素绑定其他东西到TreeView。SelectedItem,而不是将其他东西绑定到ViewModel,从而跳过所需的额外工作。
XAML:
<TreeView x:Name="myTreeView" ItemsSource="{Binding MyThingyCollection}">
.... stuff
</TreeView>
<!-- then.. somewhere else where I want to see the currently selected TreeView item: -->
<local:MyThingyDetailsView
DataContext="{Binding ElementName=myTreeView, Path=SelectedItem}" />
当然,这对于读取当前选择的项目很好,但不能设置它,这是我所需要的。
我偶然发现了这一页,寻找与原作者相同的答案,并证明了总是有不止一种方法来做这件事,解决方案对我来说甚至比这里提供的答案更容易,所以我想我不妨添加到堆中。
绑定的动机是保持良好& MVVM。ViewModel的可能用法是有一个带有名称的属性,例如“CurrentThingy”,而在其他地方,其他东西上的DataContext被绑定到“CurrentThingy”。
而不是通过额外的步骤(例如:自定义行为,第三方控制)来支持从TreeView到我的模型的良好绑定,然后从其他东西到我的模型,我的解决方案是使用简单的元素绑定其他东西到TreeView。SelectedItem,而不是将其他东西绑定到ViewModel,从而跳过所需的额外工作。
XAML:
<TreeView x:Name="myTreeView" ItemsSource="{Binding MyThingyCollection}">
.... stuff
</TreeView>
<!-- then.. somewhere else where I want to see the currently selected TreeView item: -->
<local:MyThingyDetailsView
DataContext="{Binding ElementName=myTreeView, Path=SelectedItem}" />
当然,这对于读取当前选择的项目很好,但不能设置它,这是我所需要的。
走吧
... 是一个更好的答案,但没有提到一种在ViewModel中获取/设置SelectedItem的方法。
添加一个IsSelected布尔属性到ItemViewModel,并在TreeViewItem的样式设置器中绑定到它。
在ViewModel中添加SelectedItem属性,作为TreeView的DataContext。这是上面解决方案中缺少的部分。
' ItemVM...
Public Property IsSelected As Boolean
Get
Return _func.SelectedNode Is Me
End Get
Set(value As Boolean)
If IsSelected value Then
_func.SelectedNode = If(value, Me, Nothing)
End If
RaisePropertyChange()
End Set
End Property
' TreeVM...
Public Property SelectedItem As ItemVM
Get
Return _selectedItem
End Get
Set(value As ItemVM)
If _selectedItem Is value Then
Return
End If
Dim prev = _selectedItem
_selectedItem = value
If prev IsNot Nothing Then
prev.IsSelected = False
End If
If _selectedItem IsNot Nothing Then
_selectedItem.IsSelected = True
End If
End Set
End Property
<TreeView ItemsSource="{Binding Path=TreeVM}"
BorderBrush="Transparent">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded}"/>
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
也可以使用TreeView项的IsSelected属性来完成。我是这么做的,
public delegate void TreeviewItemSelectedHandler(TreeViewItem item);
public class TreeViewItem
{
public static event TreeviewItemSelectedHandler OnItemSelected = delegate { };
public bool IsSelected
{
get { return isSelected; }
set
{
isSelected = value;
if (value)
OnItemSelected(this);
}
}
}
然后在包含TreeView绑定到的数据的ViewModel中,只需订阅TreeViewItem类中的事件。
TreeViewItem.OnItemSelected += TreeViewItemSelected;
最后,在同一个ViewModel中实现这个处理器,
private void TreeViewItemSelected(TreeViewItem item)
{
//Do something
}
当然,绑定,
<Setter Property="IsSelected" Value="{Binding IsSelected}" />