简体   繁体   English

使用HierarchialDataTemplate扩展TreeViewItem

[英]TreeViewItem IsExpanded with HierarchialDataTemplate

I am trying so set up a TreeView for a Group/User hierarchy, where a group can have users and subgroups, and subgroups also subgroups and users, and so on. 我正在尝试为组/用户层次结构设置一个TreeView,其中一个组可以具有用户和子组,子组也可以具有子组和用户,依此类推。 When I add/remove a user or group from a collection and update the view with myTreeView.Items.Refresh(); 当我从集合中添加/删除用户或组并使用myTreeView.Items.Refresh();更新视图时 all expanded TreeViewItems get closed. 所有展开的TreeViewItems都将关闭。 This is inconvenient for the user, so i am trying to expand all TreeViewItems which were expanded before. 这对用户来说很不方便,所以我正在尝试扩展之前已扩展的所有TreeViewItems。 myTreeView.SelectedItem; doesn't seem to work, it only returns a Group or User Element no TreeViewItem Element. 似乎不起作用,它仅返回GroupUser元素,而没有TreeViewItem元素。 Now, I found something here WPF DataBound treeview expand / collapse that I tried, but the compiler is telling me this now 现在,我在这里找到了我尝试过的WPF DataBound treeview展开/折叠的内容 ,但是编译器现在告诉了我

BindingExpression path error: 'IsNodeExpanded' property not found on 'object' ''User' BindingExpression路径错误:在“对象”“用户”上找不到“ IsNodeExpanded”属性

A User can't be expanded, so implementing this Field in the User class wouldn't make sense. 无法扩展用户,因此在User类中实现此Field毫无意义。 What am I doing wrong? 我究竟做错了什么? Is this even the right approach? 这是正确的方法吗?

I have following setup for my TreeView 我为TreeView进行了以下设置

<TreeView Grid.Column="0" Name="myTreeView" SelectedItemChanged="myTreeView_SelectedItemChanged" MouseDoubleClick="myTreeView_MouseDoubleClick">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type datatypes:Group}" ItemsSource="{Binding Items, UpdateSourceTrigger=PropertyChanged}">
                <TextBlock Text="{Binding Name}" FontWeight="Bold"/>
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type datatypes:User}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding LicenceUser}"/>
                </StackPanel>
            </DataTemplate>
            <Style TargetType="TreeViewItem">
                <Setter Property="IsExpanded" Value="{Binding IsNodeExpanded, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
            </Style>
        </TreeView.Resources>
    </TreeView>

For better visibility I only copy the interfaces for my classes here. 为了获得更好的可见性,我仅在此处复制类的接口。

Here the interface for my Group class 这是我的Group类的界面

interface IGroup {
    int ID { get; set; }
    string Name { get; set; }
    string Gruppe { get; set; }
    string Path { get; set; }
    Users Users { get; set; }
    ObservableCollection<object> Items { get; }
    bool IsNodeExpanded { get; set; }
    Groups SubGroups { get; set; }
}

the Items Collection in the Group class looks like this Group类中的Items Collection看起来像这样

public ObservableCollection<object> Items {
        get {
            ObservableCollection<object> childItems = new ObservableCollection<object>();
            foreach (Group item in SubGroups) {
                childItems.Add(item);
            }
            foreach (User item in Users) {
                childItems.Add(item);
            }
            return childItems;
        }
    }

and the interface for my User class 和我的User类的界面

interface IUser {
    string UserID { get; set; }
    string LicenceUser { get; set; }
    string MailAddress { get; set; }
    string ComputerName { get; set; }
    string HardDriveID { get; set; }
    string Group { get; set; }
    string Path { get; set; }
}

Thanks in advance for your help. 在此先感谢您的帮助。

The setter for IsExpanded applies to all TreeViewItems whether they're Users or Groups. IsExpanded的设置器适用于所有TreeViewItems无论它们是“用户”还是“组”。 It shouldn't stop you from compiling; 它不应该阻止您进行编译; it'll just give you a bunch of binding errors in the debug output during runtime. 它只会在运行时给您一些调试输出中的绑定错误。

If that's not acceptable, the quickest solution for your case is to make a converter that distinguishes between Users and Groups and returns false for the former (eg IsExpanded="{Binding Path=., Converter={StaticResource ItemToBooleanConverter}}" ) 如果不可接受,针对您的情况,最快的解决方案是使转换器区分用户和组,并为前者返回false(例如IsExpanded="{Binding Path=., Converter={StaticResource ItemToBooleanConverter}}"

public class ItemToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is User)
            return false;
        return ((Group)value).IsNodeExpanded;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

EDIT: This doesn't seem to work for two-way binding. 编辑:这似乎不适用于双向绑定。 What I did in a similar situation was add ITypeProvider with one Type property so that I could make the distinction between types in XAML. 我在类似情况下所做的就是添加具有一个Type属性的ITypeProvider ,以便可以区分XAML中的类型。 A DataTrigger can set the IsExpanded binding only for a particular data type. DataTrigger只能为特定数据类型设置IsExpanded绑定。 Adds mostly useless bloat to your classes, but it helps you avoid the binding errors. 给您的类增加了大部分无用的膨胀,但是它可以帮助您避免绑定错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM