如何在 DevExpress WPF 中添加 2 个不同的模型作为子节点

问题描述 投票:0回答:1

我有这门课:

public class Team
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ObservableCollection<Competency> Competencies { get; set; } = new ObservableCollection<Competency>();

    public ObservableCollection<Employee> Employees { get; set; } = new ObservableCollection<Employee>();
}

这段代码对我有用:

<Page>
    <Page.Resources>
        <model:Employee x:Key="employees" />
        <HierarchicalDataTemplate DataType="{x:Type model:Team}" ItemsSource="{Binding Employees}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Row.Name}" FontWeight="Bold" Margin="3,0,0,0" />
            </StackPanel>
        </HierarchicalDataTemplate>
        
        <DataTemplate DataType="{x:Type model:Employee}">
            <StackPanel Orientation="Vertical">
                <Border Padding="2" HorizontalAlignment="Stretch" VerticalAlignment="Center" BorderBrush="#FFC3CEDC" BorderThickness="0,1,0,0">
                    <Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="130" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <StackPanel Orientation="Horizontal" Grid.Column="0">
                            <TextBlock Text="{Binding Row.FirstName}" FontWeight="Bold" Margin="3,0,0,0" />
                            <TextBlock Text="{Binding Row.LastName}" Margin="3,0,0,0" />
                        </StackPanel>
                    </Grid>
                </Border>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <!-- TreeListControl for Teams -->
        <dxg:TreeListControl x:Name="teamEmployeesTree" Grid.Column="0" ItemsSource="{Binding TeamsItems}">
            <dxg:TreeListControl.View>
                <dxg:TreeListView 
                     TreeDerivationMode="HierarchicalDataTemplate" 
                     AutoExpandAllNodes="True" 
                     ShowCheckboxes="True" 
                     AllowRecursiveNodeChecking="False"
                     NewItemRowPosition="Top" 
                     AllowPerPixelScrolling="True"
                     TreeColumnFieldName="Name"
                     NavigationStyle="Cell"
                     AllowDragDrop="True"
                     ShowDragDropHint="False"
                     ShowNodeImages="True"
                     UseEvenRowBackground="True"
                     EnterMoveNextColumn="False"/>
            </dxg:TreeListControl.View>
            <dxg:TreeListColumn FieldName="Name" />
            <dxg:TreeListColumn FieldName="Competencies"/>
        </dxg:TreeListControl>
    </Grid>
</Page>

现在我想要的是另一种类型的子节点,所以我需要某种类型的分组:

Team (root)
 - "Employees" (fixed node text, and when I click on this to present all employees for that team)
   --Emp1
   --Emp2
 - "Competencies" - (fixed node text, and when I click on this to present all employees for that team)
   -- Competency1
   -- Competency2

我还需要复选框“Is TeamLead”,但仅限员工。

这是否可能并且每个节点组内有不同的列?

c# wpf devexpress
1个回答
0
投票

您有三个常规选项:

#1 修改数据结构。 如果您有机会修改数据结构,您可以简单地添加另一个级别,例如作为一个组的

Details
属性。

Team.cs

public class Team
{
  public int Id { get; set; }
  public string Name { get; set; }
  public ObservableCollection<ITeamDetail> Details { get; set; } = new ObservableCollection<ITeamDetail>();
}

ITeamDetail.cs

public class ITeamDetail
{
  int TeamId { get; set; }
}

能力详细信息.cs

public class CompetencyDetails : ITeamDetail
{
  public int TeamId { get; set; }
  public ObservableCollection<Competency> Competencies { get; } = new ObservableCollection<Competency>();
}

EmployeeDetails.cs

public class EmployeeDetails : ITeamDetail
{
  public int TeamId { get; set; }
  public ObservableCollection<Employee> Employees { get; } = new ObservableCollection<Employee>();
}

这将为您提供以下树结构:

Team
|__Employees
|  |__Employee1
|
|__Competencies
   |__Competency1

#2 修改

DataTemplate
如果您无法修改数据结构并且您的树是简单的一级结构,那么您可以在您在团队根模板中定义的专用
Empoloyess
中显示
Competencies
ListBox
列表。我不建议这样做,因为这会引入导航问题,因为两个
ListBox
元素将被
TreeView
解释为单个节点。该解决方案会产生最糟糕的结果。

作为第三种解决方案,您可以使用基于“扩展器控件”的自定义控件:

Generic.xaml

<Style TargetType="TeamView">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="TeamView">
        <ListBox ItemsSource="{Binding Teams}>
          <ListBox.ItemsTemplate>
            <DataTemplate DataType="Team">
              <Expander Header="{Binding Name}">
                <StackPanel>
                  <Expander Header="Employees"
                            Margin="8,0,0,0"
                            Padding="4,0,0,0">
                    <ListBox ItemsSource="{Binding Employees}" />
                  </Expander>
                  <Expander Header="Competencies"
                            Margin="8,0,0,0"
                            Padding="4,0,0,0">
                    <ListBox ItemsSource="{Binding Competencies}" />
                  </Expander>
                </StackPanel>
              </Expander>
            </DataTemplate>
          </ListBox.ItemsTemplate>
        </ListBox>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

TeamView.cs
高度专业化的控制。
您可以通过添加两个

DataTemplate
类型的依赖属性,然后将其绑定到两个内部
DataTemplate
ListBox.ItemsTemplate
 属性,使此控件接受两个级别中每一个级别的 
ListBox
 ,从而增强应用程序的可扩展性
元素。这样,更改数据模型就不会破坏该控件的模板。为简单起见,我在本示例中避免了这种开销。

您还可以覆盖默认的

ListBoxItem
模板以删除突出显示行为(只需定义不带任何触发器的普通模板)。

class TeamView : Control
{
  public IList<Team> Teams
  {
    get => (IList<Team>)GetValue(TeamsProperty);
    set => SetValue(TeamsProperty, value);
  }

  public static readonly DependencyProperty TeamsProperty = DependencyProperty.Register(
    nameof(Teams),
    typeof(IList<Team>),
    typeof(DelayButton),
    new PropertyMetadata(default));

  static TeamView()
  {
    DefaultStyleKeyProperty.OverrideMetadata(typeof(TeamView), new FrameworkPropertyMetadata(typeof(TeamView)));
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.