我正在开发一个基于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>
答案 0 :(得分:1)
我确实尝试根据一些假设制作递归模板
屏幕截图
我的课程也做了一些更改,实施的通知已更改为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>
结果