我正在使用HierarchicalDataTemplate将我的类绑定到带有复选框的TreeView。我的代码工作正常,一切都很好,但我希望能够在树视图中获得一个项目的子项列表。
单击复选框时,我希望能够选择父节点和子节点。如果我有权访问应该包装复选框的TreeViewItem,那么我可以轻松地执行此操作,但Checkbox的Parent属性为null ...我似乎只能访问在HierarchicalDataTemplate中映射的类。
<TreeView Margin="12" Name="trv1" SelectedItemChanged="trv1_SelectedItemChanged">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type src:Location}" ItemsSource="{Binding Path=Sublocations}">
<CheckBox Content="{Binding Name}" Tag="{Binding}" IsChecked="{Binding IsChecked}" Click="checkBox_Click"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type src:Sublocation}" ItemsSource="{Binding Path=Children}">
<CheckBox Content="{Binding Name}" Tag="{Binding}" IsChecked="{Binding IsChecked}" Click="checkBox_Click"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type src:Child}">
<CheckBox Content="{Binding Name}" Tag="{Binding}" IsChecked="{Binding IsChecked}" Click="checkBox_Click"/>
</DataTemplate>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsSelected" Value="{Binding IsChecked}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
答案 0 :(得分:1)
您需要在TreeViewItem类中添加Children和Parent节点。您需要在初始化时设置父/子。
<HierarchicalDataTemplate x:Key="TreeViewItem" ItemsSource="{Binding Children}">
<CheckBox Margin="2" IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Name}" />
</HierarchicalDataTemplate>
<TreeView ItemsSource="{Binding Countries}" ItemTemplate="{StaticResource TreeViewItem}" />
在你的viewModels中。
public class MainPageViewModel
{
public ObservableCollection<Country> Countries {get;set;}
}
public class Country
{
public string Name {get; set;}
public bool IsChecked {get;set;}
public IEnumerable<State> Children {get; set;}
// Do not need parent for this.
}
public class State
{
public string Name {get; set;}
public bool IsChecked {get; set;}
public Country Parent {get; set;}
public IEnumerable<City> Children {get; set;}
}
public class City
{
public string Name {get; set;}
public bool IsChecked {get; set;}
public State Parent {get; set;}
}
答案 1 :(得分:0)
我想出了一个可能不是最佳解决方案的解决方案,但它确实有效。我在TreeView样式中添加了一个EventSetter,并为TreeViewItem对象分配了一个click事件。
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsSelected" Value="{Binding IsChecked}"/>
<EventSetter Event="Selected" Handler="tvi_Selected"/>
</Style>
</TreeView.ItemContainerStyle>
这样我就可以访问发送者对象,它是一个TreeViewItem,并在节点中导航。
编辑: 这个“解决方案”只给了我最顶层的TreeViewItem对象,而不是选中的对象,它是对象的子对象。
编辑2: treeviewitems似乎实际上不允许我访问子treeviewitems或父treeviewitems。我想我错了。
答案 2 :(得分:0)
仅供参考:而不是必须获取TreeViewItem我发现最好在您的Nodes类中包含对模型中父级的引用:
Node.Parent {get{return this._parent;}}
然后在构建你的收藏时,你必须设置这些值,但它会使生活变得非常容易:想象得到你父母的任何级别:
myNode.Parent.Parent.Parent
获取TreeViewItem:(来自我的回答:How to get TreeViewItem from HierarchicalDataTemplate item?)
我必须在路由的TreeViewItem.Selected事件中设置最后一个选定的TreeViewItem,它会冒泡到树视图(TreeViewItem本身在设计时不存在,因为我们使用的是HierarchicalDataTemplate)。
事件可以在XAML中捕获,如下所示:
然后可以在事件中设置最后选择的TreeViewItem:
private void TreeViewItemSelected(object sender, RoutedEventArgs e)
{
TreeViewItem tvi = e.OriginalSource as TreeViewItem;
// set the last tree view item selected variable which may be used elsewhere as there is no other way I have found to obtain the TreeViewItem container (may be null)
this.lastSelectedTreeViewItem = tvi;
...
}
答案 3 :(得分:0)
如果您想坚持MVVM pattern,您应该执行以下操作: 选择更改时触发命令(我在谈论TreeView.SelectedItemChanged事件)。
然后,使用此命令更新视图模型中的“SelectedItems”属性。
public class MyViewModel
{
// your view model code...
// ........................
// this object better be more strongly typed
private object _mySelectedItem;
public object MySelectedItem
{
get { return _mySelectedItem; }
set {
_mySelectedItem = value;
// the following method will handle the changed item. Problem solved
HandleTheNewChangedItem(value);
}
}
}