3

我正在使用 HierarchicalDataTemplate 将我的类绑定到带有复选框的 TreeView。我的代码工作正常,一切都显示正常,但我希望能够在我的树视图中获取项目的子项列表。

单击复选框时,我希望能够选择父节点和子节点。如果我可以访问应该包装复选框的 TreeViewItem,那么我可以轻松地做到这一点,但是 Checkbox 的 Parent 属性为空......我似乎只能访问我在 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>
4

4 回答 4

1

您需要在 TreeViewItem 类中添加子节点和父节点。您需要在初始化时设置父/子。

<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}" />

在您的视图模型中。

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;}
}
于 2013-04-02T10:59:30.423 回答
0

I came up with a solution that may not be the optimal one, but it works. I added an EventSetter in the TreeView style and assigned a click event for TreeViewItem objects.

            <TreeView.ItemContainerStyle>
                <Style TargetType="TreeViewItem">
                    <Setter Property="IsSelected" Value="{Binding IsChecked}"/>
                    <EventSetter Event="Selected" Handler="tvi_Selected"/>
                </Style>
            </TreeView.ItemContainerStyle>

This way I can access the sender object, which is a TreeViewItem, and navigate through the nodes.

EDIT: This "solution" only gives me the top TreeViewItem object and not the selected one, which is a child of the object.

EDIT 2: The treeviewitems don't seem to actually let me access child treeviewitems or parent treeviewitems. I guess I was wrong.

于 2010-07-05T16:57:09.803 回答
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;

    ...
 }
于 2010-11-15T02:45:17.810 回答
0

If you want to stick to the MVVM pattern , you should do the following: trigger a command when the selection changes (I'm talking about the TreeView.SelectedItemChanged event).

然后,使用此命令更新视图模型中的“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);
            }
    }
}
于 2011-01-25T21:36:20.267 回答