2010-08-11 310 views

回答

3
+0

但我想混合它与DataGrid(可编辑) – Shimmy 2010-08-11 11:07:27

+1

+1 @Shimmy请参阅com是http://www.codeproject.com/KB/WPF/wpf_treelistview_control.aspx的一部分。它显示了如何使用它,而不是一个列表视图 – k3b 2011-03-23 14:56:45

+0

@ k3b你应该指示这个@Hedge。我认为这不是一个真正的问题@Shimmy关心了......只是说... – 2011-03-24 23:07:57

7

这在我看来就像一个相当简单的事情,如果你正确地设计您的视图模型来实现。

基本上,设计项目的方式与在正常数据网格中显示它们时的方式相同,即每个项目对每个列都有一个属性。很有可能,您的底层数据模型是分层的,但网格绑定的集合将被展平,即不管父/子关系如何,都将包含层次结构中每个节点的项目。

项目视图模型具有一些额外的属性:LevelChildrenIsExpanded,并IsVisibleLevel是节点祖先的计数,Children包含子视图模型节点,在用户界面中使用IsExpanded,如果节点可见,则IsVisible为真。它还实现了一个名为VisibleDescendants属性:

public IEnumerable<NodeViewModel> VisibleDescendants 
{ 
    get 
    { 
     return Children 
      .Where(x => x.IsVisible) 
      .SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants))); 
    } 
} 

您使用LevelHasChildrenIsExpanded在样式在控件的第一列的项目:他们所控制的左边空白,什么图标的种类(如果有的话)显示。

您还需要执行ExpandCommandCollapseCommand属性。如果Children.Any()为真且IsExpanded为假,则启用ExpandCommand,并且如果Children.Any()为真并且IsExpanded为真,则启用CollapseCommand。这些命令在执行时会更改IsExpanded的值。

这就是它变得有趣的地方。实现此功能的简单方法可能适用于您:这些项目由父视图模型公开,该视图模型的Items属性不是集合。相反,它是向下传播子视图模型的链,只产生可见的节点枚举:

public IEnumerable<NodeViewModel> Items 
{ 
    get 
    { 
     return _Items 
      .Where(x => x.IsVisible) 
      .SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants)); 
    } 
} 

每当任何后代的IsVisible属性更改,父视图模型提出了PropertyChangedItems财产,这迫使数据网格重新填充。

有一个不太简单的实现过,在这里你做出Items属性,实现INotifyCollectionChanged一类,而且提高了正确CollectionChanged活动时,子节点成为可见/不可见,但你只想去那里,如果性能是一个问题。

+0

这真棒! – faztp12 2015-12-13 09:29:18

2

以下的答案必须从@Robert Rossney的答案开发:

public class DataGridHierarchialDataModel 
{ 

    public DataGridHierarchialDataModel() { Children = new List<DataGridHierarchialDataModel>(); } 


    public DataGridHierarchialDataModel Parent { get; set; } 
    public DataGridHierarchialData DataManager { get; set; } 
    public void AddChild(DataGridHierarchialDataModel t) 
    { 
     t.Parent = this; 
     Children.Add(t); 
    } 


    #region LEVEL 
    private int _level = -1; 
    public int Level 
    { 
     get 
     { 
      if (_level == -1) 
      {      
       _level = (Parent != null) ? Parent.Level + 1 : 0; 
      } 
      return _level; 
     } 
    } 

    #endregion 
    public bool IsExpanded 
    { 
     get { return _expanded; } 
     set 
     { 
      if (_expanded != value) 
      { 
       _expanded = value; 
       if (_expanded == true) 
        Expand(); 
       else 
        Collapse(); 
      } 
     } 
    } 


    public bool IsVisible 
    { 
     get { return _visible; } 
     set 
     { 
      if (_visible != value) 
      { 
       _visible = value; 
       if (_visible) 
        ShowChildren(); 
       else 
        HideChildren(); 
      } 
     } 
    } 
    public bool HasChildren { get { return Children.Count > 0; } } 
    public List<DataGridHierarchialDataModel> Children { get; set; } 



    public object Data { get; set; } // the Data (Specify Binding as such {Binding Data.Field}) 

    public IEnumerable<DataGridHierarchialDataModel> VisibleDescendants 
    { 
     get 
     {    
      return Children 
       .Where(x => x.IsVisible) 
       .SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants));    
     } 
    } 



    // Expand Collapse 
    private bool _expanded = false; 
    private bool _visible = false; 
    private void Collapse() 
    { 
     DataManager.RemoveChildren(this); 
     foreach (DataGridHierarchialDataModel d in Children) 
      d.IsVisible = false; 
    } 

    private void Expand() 
    { 
     DataManager.AddChildren(this); 
     foreach (DataGridHierarchialDataModel d in Children) 
      d.IsVisible = true; 
    } 




    // Only if this is Expanded 
    private void HideChildren() 
    { 
     if (IsExpanded) 
     { 
      // Following Order is Critical 
      DataManager.RemoveChildren(this); 
      foreach (DataGridHierarchialDataModel d in Children) 
       d.IsVisible = false; 
     } 
    } 
    private void ShowChildren() 
    { 
     if (IsExpanded) 
     { 
      // Following Order is Critical 
      DataManager.AddChildren(this); 
      foreach (DataGridHierarchialDataModel d in Children) 
       d.IsVisible = true; 
     } 
    } 
} 

public class DataGridHierarchialData : ObservableCollection<DataGridHierarchialDataModel> 
{ 

    public List<DataGridHierarchialDataModel> RawData { get; set; } 
    public DataGridHierarchialData() { RawData = new List<DataGridHierarchialDataModel>(); } 

    public void Initialize() 
    { 
     this.Clear(); 
     foreach (DataGridHierarchialDataModel m in RawData.Where(c => c.IsVisible).SelectMany(x => new[] { x }.Concat(x.VisibleDescendants))) 
     {     
      this.Add(m); 
     } 
    } 

    public void AddChildren(DataGridHierarchialDataModel d) 
    { 
     if (!this.Contains(d)) 
      return; 
     int parentIndex = this.IndexOf(d); 
     foreach (DataGridHierarchialDataModel c in d.Children) 
     { 
      parentIndex += 1; 
      this.Insert(parentIndex, c); 
     } 
    } 

    public void RemoveChildren(DataGridHierarchialDataModel d) 
    { 
     foreach (DataGridHierarchialDataModel c in d.Children) 
     { 
      if (this.Contains(c)) 
       this.Remove(c); 
     } 
    } 
} 

上面类是什么他解释说。 使用DataGridHierarchialDataModel中的Data对象放置您自己的自定义数据,并生成您的等级数据并将其放入DataGridHierarchialDataRawData。万一完成时致电Initialize;

DataTable accTable = await DB.getDataTable("SELECT * FROM Fm3('l1')"); 
     accTable.DefaultView.Sort = "iParent"; 

     DataGridHierarchialData data = new DataGridHierarchialData(); 

     Action<DataRowView, DataGridHierarchialDataModel> Sort = null; 
     Sort = new Action<DataRowView, DataGridHierarchialDataModel>((row, parent) => 
     { 
      DataGridHierarchialDataModel t = new DataGridHierarchialDataModel() { Data = row, DataManager = data }; 
      if (row["iGroup"].ToString() == "1") 
      {      
       foreach (DataRowView r in accTable.DefaultView.FindRows(row["iSmajId"])) 
        Sort(r, t); 
      } 
      parent.AddChild(t); 
     }); 

     foreach (DataRowView r in accTable.DefaultView.FindRows(0)) 
     { 
      DataGridHierarchialDataModel t = new DataGridHierarchialDataModel() { Data = r, DataManager = data }; 
      if (r["iGroup"].ToString() == "1") 
      {      
       foreach (DataRowView rf in accTable.DefaultView.FindRows(r["iSmajId"])) 
        Sort(rf, t); 
      } 

      t.IsVisible = true; // first layer 
      data.RawData.Add(t); 
     } 
     data.Initialize(); 
     dg.ItemsSource = data; 

^这是我的情况下,以组帐户

XAML:

<DataGrid x:Name="dg" AutoGenerateColumns="False" IsReadOnly="False" CanUserAddRows="False" GridLinesVisibility="All" ColumnWidth="*"> 

     <DataGrid.Columns> 
      <DataGridTextColumn Header="Name" Binding="{Binding Data.sName}"> 
       <DataGridTextColumn.CellStyle> 
        <Style TargetType="DataGridCell" BasedOn="{StaticResource MetroDataGridCell}"> 
         <Setter Property="Template"> 
          <Setter.Value> 

           <ControlTemplate TargetType="DataGridCell"> 
            <Border BorderBrush="{TemplateBinding BorderBrush}" 
             BorderThickness="{TemplateBinding BorderThickness}" 
             Background="{TemplateBinding Background}" 
             SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"> 

             <StackPanel Orientation="Horizontal"> 
              <ToggleButton x:Name="Expander"            
              Margin="{Binding Level,Converter={StaticResource LevelToIndentConverter}}" 
              IsChecked="{Binding Path=IsExpanded, UpdateSourceTrigger=PropertyChanged}" 
              ClickMode="Press" > 
               <ToggleButton.Style> 
                <Style TargetType="{x:Type ToggleButton}"> 
                 <Setter Property="Focusable" Value="False"/> 
                 <Setter Property="Width" Value="19"/> 
                 <Setter Property="Height" Value="13"/> 
                 <Setter Property="Template"> 
                  <Setter.Value> 
                   <ControlTemplate TargetType="{x:Type ToggleButton}"> 
                    <Border Width="19" Height="13" Background="Transparent"> 
                     <Border Width="9" Height="9" 
                       BorderThickness="0" 
                       BorderBrush="#FF7898B5" 
                       CornerRadius="1" 
                       SnapsToDevicePixels="true"> 
                      <Border.Background> 
                       <SolidColorBrush Color="Transparent"/> 
                       <!-- 
                        <LinearGradientBrush StartPoint="0,0" 
                         EndPoint="1,1"> 
                         <LinearGradientBrush.GradientStops> 
                          <GradientStop Color="White" 
                        Offset=".2"/> 
                          <GradientStop Color="#FFC0B7A6" 
                        Offset="1"/> 
                         </LinearGradientBrush.GradientStops> 
                        </LinearGradientBrush> 
                       --> 
                      </Border.Background> 
                      <Path x:Name="ExpandPath"          
                      Data="M0,0 L0,6 L6,0 z" 
                      Fill="Transparent" 
                      Stroke="{DynamicResource BlackBrush}" Margin="1,2,1,1"> 
                       <Path.RenderTransform> 
                        <RotateTransform Angle="135" 
                        CenterY="3" 
                        CenterX="3" /> 
                       </Path.RenderTransform> 
                      </Path> 
                      <!-- 
                      <Path x:Name="ExpandPath" 
                      Margin="1,1,1,1" 
                      Fill="Black" 
                      Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z"/> 
                      --> 
                     </Border> 
                    </Border> 
                    <ControlTemplate.Triggers> 
                     <Trigger Property="IsChecked" 
                      Value="True"> 
                      <Setter Property="RenderTransform" 
                       TargetName="ExpandPath"> 
                       <Setter.Value> 
                        <RotateTransform Angle="180" 
                        CenterY="3" 
                        CenterX="3" /> 
                       </Setter.Value> 
                      </Setter> 
                      <Setter Property="Fill" 
                       TargetName="ExpandPath" 
                       Value="{DynamicResource GrayBrush1}" /> 
                      <Setter Property="Stroke" 
                       TargetName="ExpandPath" 
                       Value="{DynamicResource BlackBrush}" /> 

                       <!-- 
                        <Setter Property="Data" 
                      TargetName="ExpandPath" 
                      Value="M 0 2 L 0 3 L 5 3 L 5 2 Z"/> 
                      --> 
                     </Trigger> 
                    </ControlTemplate.Triggers> 
                   </ControlTemplate> 
                  </Setter.Value> 
                 </Setter> 
                </Style> 
               </ToggleButton.Style> 
              </ToggleButton> 

              <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" 
                 Content="{TemplateBinding Content}" 
                 ContentStringFormat="{TemplateBinding ContentStringFormat}" 
                 Margin="{TemplateBinding Padding}" 
                 SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                 VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                 HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" /> 


             </StackPanel> 
            </Border> 
            <ControlTemplate.Triggers> 
             <DataTrigger Binding="{Binding HasChildren}" Value="False"> 
              <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/> 
             </DataTrigger> 
            </ControlTemplate.Triggers> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </DataGridTextColumn.CellStyle> 
      </DataGridTextColumn> 
      <DataGridTextColumn Header="Code" Binding="{Binding Data.sCode}"/> 
      <DataGridTextColumn Header="Type" Binding="{Binding Data.c867x1}"/> 

     </DataGrid.Columns> 
    </DataGrid> 

那大:P,但相信我,罗伯特Rossney的想法是一个爆炸:) 此外,扩展“ +',' - '样式也包括在内(注释掉) 希望它有帮助:)