【问题标题】:Changing the collection of Itemsource Dynamically in HierarchialDataTemplate of TreeView在 TreeView 的 HierarchialDataTemplate 中动态更改 Itemsource 的集合
【发布时间】:2019-09-10 13:25:01
【问题描述】:

TreeView 必须以递归方式填充不同的集合。

当我从第二级只有一种类型的集合时,我能够完美地填充。但是现在我需要在二级之后处理两个不同的集合。

我尝试创建 ViewModelBase 类的 Observable Collection,它实际上扩展到所有其他 ViewModel 类,我认为我可以将任何类型的 ViewModel 实例添加到 Observable Collection。但是,当我不必一次处理两个不同的集合时,这将起作用。

<HierarchicalDataTemplate DataType="{x:Type VM:ViewModelBase}" ItemsSource="{Binding SecondViewModelCollection}">
                        <StackPanel Orientation="Horizontal" >
                            <Image Source="../resources/New_Package.png" Width="15" Height="15"/>
                            <TextBlock Text="{Binding Header}" Loaded="Project_Loaded"></TextBlock>
                        </StackPanel>
                        <HierarchicalDataTemplate.ItemTemplate>
                            <HierarchicalDataTemplate DataType="{x:Type VM:ViewModelBase}" ItemsSource="{Binding ThirdViewModelCollection}">
                                <StackPanel Orientation="Horizontal" >
                                    <Image Source="../resources/New_Package.png" Width="15" Height="15"/>
                                    <TextBlock Text="{Binding Header}"></TextBlock>
                                </StackPanel>
                                <HierarchicalDataTemplate.ItemTemplate>
                                    <HierarchicalDataTemplate DataType="{x:Type VM:ViewModelBase}" ItemsSource="{Binding FourthViewModelBaseCollection}">
                                        <StackPanel Orientation="Horizontal">
                                            <Image Source="../resources/New_Package.png" Width="15" Height="15"/>
                                            <TextBlock Text="{Binding Header}"  MouseDown="TextBlock_MouseUp" 
                                                       Loaded="TextBlock_Loaded" Focusable="True"/>
                                            <TextBox LostFocus="TextBox_LostFocus" Visibility="Collapsed" MouseEnter="TextBox_MouseEnter"/>
                                        </StackPanel>
                                        <HierarchicalDataTemplate.ItemTemplate>
                                            <HierarchicalDataTemplate DataType="{x:Type VM:ViewModelBase}" ItemsSource="{Binding FeatureViewModelCollection}">
                                                <StackPanel Orientation="Horizontal">
                                                    <Image Source="../resources/file.png" Width="15" Height="15"/>
                                                    <TextBlock Text="{Binding Header}"/>
                                                </StackPanel>
                                                <HierarchicalDataTemplate.ItemTemplate>
                                                    <HierarchicalDataTemplate DataType="{x:Type VM:ViewModelBase}" ItemsSource="{Binding Usecaselist}">
                                                        <StackPanel>
                                                            <TextBlock Text="{Binding Header}"  MouseDown="TextBlock_MouseUp" 
                                                                       Loaded="TextBlock_Loaded" Focusable="True" />

                                                            <TextBox LostFocus="TextBox_LostFocus" Visibility="Collapsed" MouseEnter="TextBox_MouseEnter"/>

                                                        </StackPanel>
                                                        <HierarchicalDataTemplate.ItemTemplate>
                                                            <DataTemplate DataType="{x:Type VM:ViewModelBase}">
                                                                <StackPanel >
                                                                    <TextBlock Text="{Binding Header}" MouseDown="TextBlock_MouseUp"  
                                                                               Loaded="TextBlock_Loaded"  Focusable="True" />

                                                                    <TextBox 
                                                                             LostFocus="TextBox_LostFocus" Visibility="Collapsed"
                                                                             MouseEnter="TextBox_MouseEnter" >
                                                                    </TextBox>
                                                                </StackPanel>
                                                            </DataTemplate>
                                                        </HierarchicalDataTemplate.ItemTemplate>

                                                    </HierarchicalDataTemplate>
                                                </HierarchicalDataTemplate.ItemTemplate>
                                            </HierarchicalDataTemplate>
                                        </HierarchicalDataTemplate.ItemTemplate>
                                    </HierarchicalDataTemplate>
                                </HierarchicalDataTemplate.ItemTemplate>
                            </HierarchicalDataTemplate>
                        </HierarchicalDataTemplate.ItemTemplate>
public class ViewModelBase : INotifyPropertyChanged
{
     public event PropertyChangedEventHandler PropertyChanged;

     protected void OnPropertyChanged(String propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
}
> Level 1
      > Level 2.1 (Diff class with diff. collection)
         > Level 3.1 (Diff from other 3.1)
           > Level 4.1
           > Level 4.2
         > Level 3.2 (Diff from other 3.2)
         > Level 3.3 (Diff from other 3.3)
      > Level 2.2 (Diff class with diff. collection)
         > Level 3.1 (Diff from other 3.1)
         > Level 3.2 (Diff from other 3.2)
      > Level 2.3 (Diff class with diff. collection)
         > Level 3.1 (Diff from other 3.1)
         > Level 3.2 (Diff from other 3.2)

现在ThirdViewModelCollection的Objects有两种类型,不只是datatype/object不同,它们里面的collection也会和这里不同。

【问题讨论】:

标签: c# wpf xaml treeview itemsource


【解决方案1】:

要求所有数据类型都必须扩展一个通用的基本类型(例如ViewModelBase)。然后,您可以(并且应该)混合包含在该公共基本类型的集合中的类型(例如ObservableCollection&lt;ViewModeBase&gt;),以便每个节点都有一个集合,其中包含扩展公共树的基本类型的子项。
然后使用DataTemplateSelector 为节点类型返回适当的DataTemplate

这样,只要每个可能的节点类型存在DataTemplate,TreeView 就会动态生成,无论宽度或高度。

动态TreeView

<TreeView ItemsSource="{Binding Items}"
          ItemTemplateSelector="{DynamicResource DataTemplateSelector}">
  <TreeView.Resources>
    <local:DataTemplateSelector x:Key="DataTemplateSelector" />

<!-- The DataTemplates for each node type -->   
    <HierarchicalDataTemplate x:Key="FirstDataTemplate"
                              DataType="FirstViewModel"
                              ItemsSource="{Binding ChildItems}">
      <TextBlock Text="{Binding Name}" />
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate x:Key="SecondDataTemplate"
                              DataType="SecondViewModel"
                              ItemsSource="{Binding ChildItems}">
      <TextBlock Text="{Binding Name}" />
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate x:Key="ThirdDataTemplate"
                              DataType="ThirdViewModel"
                              ItemsSource="{Binding ChildItems}">
      <TextBlock Text="{Binding Name}" />
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate x:Key="IndFeatureDataTemplate"
                              DataType="IndFeatureViewModel"
                              ItemsSource="{Binding ChildItems}">
      <TextBlock Text="{Binding Name}" />
    </HierarchicalDataTemplate>

    <DataTemplate x:Key="IndUsecaseDataTemplate"
                  DataType="IndUsecaseViewModel">
      <TextBlock Text="{Binding Name}" />
    </DataTemplate>
  </TreeView.Resources>
</TreeView>

TreeView 的 DataTemplateSelector

class DataTemplateSelector : System.Windows.Controls.DataTemplateSelector
{
  public override DataTemplate
    SelectTemplate(object item, DependencyObject container)
  {
    FrameworkElement element = container as FrameworkElement;

     return item is FirstViewModel 
       ? element.FindResource("FirstDataTemplate") as DataTemplate 
       : item is SecondViewModel 
         ? element.FindResource("SecondDataTemplate") as DataTemplate
         : item is ThirdViewModel 
           ? element.FindResource("ThirdDataTemplate") as DataTemplate
           : item is IndFeatureViewModel
             ? element.FindResource("IndFeatureDataTemplate") as DataTemplate
             : element.FindResource("IndUsecaseDataTemplate") as DataTemplate;
  }
}

常见的基本类型

public abstract class ViewModelbase
{
  public ObservableCollection<ViewModelBase> ChildItems { get;set; }   
  public string Name { get;set; }    
}

扩展型

public class FirstViewModel : ViewModelbase
{
  public FirstViewModel() 
  {
    // Create a collection with mixed types all derived from ViewModellBase
    this.ChildItems = new ObservableCollection<ViewModeLBase>() 
    { 
      new SecondViewModel(), 
      new ThirdViewModel(),
      new IndUsecaseViewModel()
    };
  }

  public ObservableCollection<ViewModelBase> ChildItems { get;set; }    
}

【讨论】:

  • 感谢您的回复。在这个答案中,它展示了如何解决不同数据类型的问题,我在我的项目中采用了相同的方法。但我的问题是具有不同集合的类,而 ViewModelBase 不是我的抽象类,因为它用于实现 INotifyPropertyChanged。我已经更新了这个问题。如果我遗漏了什么,请告诉我。
猜你喜欢
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多