无限嵌套DataGrid数据模板

时间:2014-07-05 12:00:40

标签: c# wpf mvvm datagrid datatable

我正在开发一个基于MVVM的wpf应用程序。我所做的就是尝试将Nested DataGrids与我的DataTable绑定。我有类CustomTable

public class CustomTable : INotifyPropertyChanged
{
        public List<DataTable> Main { get; set; }
        public CustomTable Child { get; set; } 
        public DataRowView _selectedItem;
        public DataRowView SelectedItem
        {
            get
            {
                return _selectedItem;
            }
            set
            {
                _selectedItem = value;
                Child = new CustomTable();
                OnPropertyChanged("SelectedItem");
            }
        }  

        public CustomTable()
        {
            Main = new List<DataTable>();
            Main.Add(someRandomTable());

        }

        private DataTable someRandomTable()
        {
            DataTable table = new DataTable();
            table.Columns.Add("Dosage", typeof(int));
            table.Columns.Add("Drug", typeof(string));
            table.Columns.Add("Patient", typeof(string));
            table.Columns.Add("Date", typeof(DateTime));
            table.Rows.Add(25, "Indocin", "David", DateTime.Now);
            table.Rows.Add(50, "Enebrel", "Sam", DateTime.Now);
            table.Rows.Add(10, "Hydralazine", "Christoff", DateTime.Now);
            table.Rows.Add(21, "Combivent", "Janet", DateTime.Now);
            table.Rows.Add(100, "Dilantin", "Melanie", DateTime.Now);
            return table;
        }



        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string caller)
        {

            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(caller));
            }
        }

}

自定义表由DataTables列表组成 - &gt; CustomTable类型的Main,SelectedItem和Child。我正在为这个类实现INotifyPropertyChanged。

所以我有ItemsControl,其DataContext是这个类,ItemSource绑定到Main。而我的ItemControl.Template由DataGrid组成。在成功运行时,显示没有绑定到主列表中每个元素的DataGrids。现在我将DataGrid的SelectedItem属性绑定到CustomTable的SelectedItem属性。我也能做到这一点。现在,当我选择一行并调用customTable的SelectedItem的setter时,我正在创建具有预定义Main的Child的新实例(仅作为示例,实际逻辑很复杂且与问题无关)。现在我想将我的Child绑定到我的selectesRow的 RowDetailsTemplate ,以便显示嵌套的dataGrids。这应该是递归的,比如单击Child的DataGrid中的一行也应该显示Child-&gt; Child-&gt; Main。 我无法实现这一目标,并且在没有进展的情况下尝试了最后几天。除此之外的任何其他方法也受到欢迎。

修改

XAML文件

<Window x:Class="HierDataGrid.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:tvcc="clr-namespace:HierDataGrid"
    Title="MainWindow" Height="350" Width="525" xmlns:metro="http://schemas.codeplex.com/elysium">
<Window.Resources>
    <DataTemplate x:Key="Nested">

        <ItemsControl ItemsSource="{Binding DataContext.Tables, RelativeSource={RelativeSource AncestorType=DataGrid, Mode=FindAncestor}}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                    <DataGrid CanUserAddRows="False" RowDetailsTemplate="{DynamicResource Nested}" ItemsSource="{Binding Main}" AutoGenerateColumns="True" >
                    </DataGrid>
                </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
    </DataTemplate>
</Window.Resources>


<ScrollViewer DataContext="{Binding}">
    <StackPanel>

        <ItemsControl ItemsSource="{Binding Path=TableCollection.Main}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                    <DataGrid Name="dg" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" CanUserAddRows="False" RowDetailsTemplate="{StaticResource Nested}"   ItemsSource="{Binding}" AutoGenerateColumns="True" >

                    </DataGrid>
                </DataTemplate>
        </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</ScrollViewer>

1 个答案:

答案 0 :(得分:1)

我确实尝试根据一些假设制作递归模板

屏幕截图

screen

我的课程也做了一些更改,实施的通知已更改为Child属性

    private CustomTable _child;
    public CustomTable Child
    {
        get
        {
            return _child;
        }
        set
        {
            _child = value;
            OnPropertyChanged("Child");
        }
    }
其他人可以在需要时完成

XAML

<ScrollViewer>
    <ScrollViewer.Resources>
        <DataTemplate DataType="{x:Type l:CustomTable}">
            <StackPanel>
                <ItemsControl ItemsSource="{Binding Path=Main}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <DataGrid SelectedItem="{Binding DataContext.SelectedItem, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor,AncestorType=ItemsControl}}"
                                      CanUserAddRows="False"  ItemsSource="{Binding}" AutoGenerateColumns="True" />
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
                <Expander Header="Child" Margin="10" IsExpanded="True" x:Name="child">
                    <ContentControl Content="{Binding Child}"/>
                </Expander>
            </StackPanel>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Child}" Value="{x:Null}">
                    <Setter TargetName="child" Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ScrollViewer.Resources>

    <ContentControl Content="{Binding TableCollection}"/>

</ScrollViewer>
上面示例中的

l:引用了类CustomTable的名称空间,用此替换了您的xaml。您也可以删除窗口资源中的模板。

我还重组了模板

  • 删除了指定的模板,并为CustomTable创建了一个数据模板。
  • 使用ContentControl绑定到TableCollection,WPF将解析我们定义的模板。
  • 同样适用于与ContentControl
  • 绑定的DataTemplate中的Child

所以这将创建一个递归模板,如屏幕截图

您可以根据需要调整模板。如果您需要任何澄清,请询问。

行级孩子

XAML

<ScrollViewer>
    <ScrollViewer.Resources>
        <DataTemplate DataType="{x:Type l:CustomTable}">
            <StackPanel>
                <ItemsControl ItemsSource="{Binding Path=Main}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <DataGrid Name="dg" SelectedItem="{Binding DataContext.SelectedItem, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor,AncestorType=ItemsControl}}"
                                  CanUserAddRows="False"  ItemsSource="{Binding}" AutoGenerateColumns="True" >
                                <DataGrid.RowDetailsTemplate>
                                    <DataTemplate>
                                        <ContentControl Margin="10"
                                                        Content="{Binding DataContext.Child, RelativeSource={RelativeSource FindAncestor,AncestorType=ItemsControl,AncestorLevel=2}}"/>
                                    </DataTemplate>
                                </DataGrid.RowDetailsTemplate>
                            </DataGrid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </StackPanel>
        </DataTemplate>
    </ScrollViewer.Resources>

    <ContentControl Content="{Binding TableCollection}"/>

</ScrollViewer>

结果

result