Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 根据嵌套类型使用自定义加载方法延迟加载TreeViewItem_C#_Wpf_Treeview_Lazy Loading - Fatal编程技术网

C# 根据嵌套类型使用自定义加载方法延迟加载TreeViewItem

C# 根据嵌套类型使用自定义加载方法延迟加载TreeViewItem,c#,wpf,treeview,lazy-loading,C#,Wpf,Treeview,Lazy Loading,假设我有一群员工。员工可以是高级主管、初级主管或实习生。 这3种类型的雇员是从employee派生的类。每个高级主管指定一组初级主管。每个初级主管指导一组学员 LoadChilds填充Childs集合 现在,我想通过使用惰性初始化在树状视图中显示他们从高级到受训人员的层次结构。我想在treevieItem.exampland事件上调用方法LoadChilds。(我对其他想法持开放态度。) 目前,我通过HierarchycalDataTemplate呈现不同的数据类型 <TreeView

假设我有一群员工。员工可以是高级主管、初级主管或实习生。 这3种类型的雇员是从employee派生的类。每个高级主管指定一组初级主管。每个初级主管指导一组学员

LoadChilds
填充
Childs
集合

现在,我想通过使用惰性初始化树状视图中显示他们从高级到受训人员的层次结构。我想在
treevieItem.exampland
事件上调用方法
LoadChilds
。(我对其他想法持开放态度。)

目前,我通过HierarchycalDataTemplate呈现不同的数据类型

<TreeView x:Name="Tree">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type model:Supervisor}" ItemsSource="{Binding Childs}">
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="{x:Type model:Employee}" ItemsSource="{Binding Childs}">
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>


问题:我如何调用方法、编辑数据并在展开树视图项时刷新UI?

您可以定义一个接口,该接口由
a
B
实现,并将展开的
树视图项的
DataContext
强制转换为以下类型:

public interface ICommon
{
    string Name { get; set; }
    void LoadChilds(DBConnection connection);
}

public class A : ICommon
{
    public class A()
    {
        Childs = new ObservableCollection<B>();
    }
    public string Name { get; set; }
    public ObservableCollection<B> Childs { get; set; }
    public void LoadChilds(DBConnection connection) //Type is unimportant
    {
        // adding childs
    }
}

public class B : ICommon
{
    public class B()
    {
        Childs = new ObservableCollection<B>(); //Yes, rekursiv
    }
    public string Name { get; set; }
    public ObservableCollection<B> Childs { get; set; }
    public void LoadChilds(DBConnection connection)
    {
        // adding childs
    } 
}
肯定有一种“更漂亮”的方法——不用在代码隐藏的事件处理程序中编写业务逻辑

在视图模型类中引入boolean
IsExpanded
,将
TreeViewItem.IsExpanded
绑定到该属性,并在setter中触发
LoadChilds
方法:

<TreeView x:Name="Tree">
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}"/>
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type model:A}" ItemsSource="{Binding Childs}">
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="{x:Type model:B}" ItemsSource="{Binding Childs}">
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

现在我做了一些类似的事情。有“更漂亮”的方法吗?我希望尽可能避免依赖关系。接口是依赖关系。“接口是依赖关系”应该是一个抽象的接口。不,没有“更漂亮”的方法。如果你没有实现一个接口,你将不得不尝试将DataContext转换为A、B、C以及任何其他可能涉及的具体类型。我的问题仅仅设置为“暂停”对我没有帮助。说不清楚的就行了。特别是其他人理解这个问题,并且已经给出了解决方案。
<TreeView x:Name="Tree">
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}"/>
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type model:A}" ItemsSource="{Binding Childs}">
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="{x:Type model:B}" ItemsSource="{Binding Childs}">
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>
public class A
{
    public A()
    {
        // null is a placeholder. 
        // without any items TreeViewItem will not even show expander
        // (Expand event won't work either)
        Childs = new ObservableCollection<B>() { null };
    }

    public string Name { get; set; }

    private bool _isExpanded;
    public bool IsExpanded
    {
        get
        {
            return _isExpanded;
        }
        set
        {
            _isExpanded = value;
            // when node is expanded, RELOAD!
            if (_isExpanded)
                LoadChilds();
        }
    }

    public ObservableCollection<B> Childs { get; set; }

    public void LoadChilds()
    {
        Childs.Clear();
        Childs.Add(new B() { Name = Guid.NewGuid().ToString() });
    }
}
public class B
{
    public B()
    {
        Childs = new ObservableCollection<B>() { null };
    }

    public string Name { get; set; }

    private bool _isExpanded;
    public bool IsExpanded
    {
        get
        {
            return _isExpanded;
        }
        set
        {
            _isExpanded = value;
            if (_isExpanded)
                LoadChilds();
        }
    }

    public ObservableCollection<B> Childs { get; set; }

    public void LoadChilds()
    {
        Childs.Clear();
        Childs.Add(new B() { Name = Guid.NewGuid().ToString() });
    }
}