DataRow 中 DataRowTemplate 内的 WPF DataTable

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

我正在 DataRowTemplate 中寻找无限嵌套的 DataGrid。因此,当单击行时,我想显示另一个 DataGrid 等。我的主类是“CustomTable”,它继承自 BaseViewModel,该类提供 PropertyChanged 事件来更新视图。

这是我的.cs:

public class CustomTable : BaseViewModel
{
private ObservableCollection<DataTable> _main;
public ObservableCollection<DataTable> Main
{
  get
  {
    return _main;
  }
  set
  {
    _main = value;
    RaisePropertyChanged();
  }
}


private CustomTable _child;
public CustomTable Child
{
  get
  {
    return _child;
  }
  set
  {
    _child = value;
    RaisePropertyChanged();
  }
}


private DataRowView _selectedItem;
public DataRowView SelectedItem
{
  get
  {
    return _selectedItem;
  }
  set
  {
    _selectedItem = value;
    Child = new CustomTable();
    RaisePropertyChanged();
  }
}


private ContentControl _tableCollection;
public ContentControl TableCollection
{
  get
  {
    return _tableCollection;
  }
  set
  {
    _tableCollection = value;
    RaisePropertyChanged();
  }
}


public CustomTable()
{
  Main = new ObservableCollection<DataTable>();
  Main.Add(someRandomTable());
  
  TableCollection = new ContentControl();
  TableCollection.Content = Main;
}

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);
  table.Rows.Add(53, "ACC", "Foobar", DateTime.Now);
  return table;
}

}

这是我的 xaml:

<Window.DataContext>
  <local:CustomTable/>
</Window.DataContext>

<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>
  <ScrollViewer.Resources>
    <DataTemplate DataType="{x:Type local:CustomTable}">
      <StackPanel>
        <ItemsControl ItemsSource="{Binding Path=Main}">
          <ItemsControl.ItemTemplate>
            <DataTemplate>
              <DataGrid SelectedItem="{Binding 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>

我不明白为什么我的输出看起来像这样:

我从无限嵌套的DataGrid数据模板中得到了一些灵感,但这并没有真正的帮助。我还不能发表评论,被迫在这里寻求帮助。

我真的不明白问题出在哪里。感谢您的帮助!!!

wpf mvvm datatable
1个回答
0
投票

为了获得准确的答案,需要一个最小的可重复示例。如果您可以将其发布到 GitHub 上并提供指向它的链接,那将会非常有帮助。这将使我们不再局限于一般性的言语和建议,而是向您展示解决方案。

我将根据对您发布的代码片段的分析得出的假设来写下我的建议和评论。

  1. 主视图创建一个 ItemsControl,显示根
    ObservableCollection<DataTable> Main
    CustomTable
    属性中的表集合。 至少,您需要从
    ContentControl TableCollection
    中删除
    CustomTable
    属性。这是一个 Visual 类,不应位于 ViewModel 中。此外,绑定到
    ContentControl.Conten
    属性的视觉类会导致数据模板被忽略。此行为内置于
    ContentControl
    逻辑中。
    public class CustomTable : BaseViewModel
    {
        //private ObservableCollection<DataTable> _main;
        public ObservableCollection<DataTable> Main { get; }
        //{
        //    get
        //    {
        //        return _main;
        //    }
        //    set
        //    {
        //        _main = value;
        //        RaisePropertyChanged();
        //    }
        //}


        private CustomTable? _child;
        public CustomTable? Child
        {
            get
            {
                return _child;
            }
            set
            {
                _child = value;
                RaisePropertyChanged();
            }
        }


        private DataRowView? _selectedItem;
        public DataRowView? SelectedItem
        {
            get
            {
                return _selectedItem;
            }
            set
            {
                _selectedItem = value;
                Child ??= new CustomTable();
                RaisePropertyChanged();
            }
        }


        //private ContentControl? _tableCollection;
        //public ContentControl? TableCollection
        //{
        //    get
        //    {
        //        return _tableCollection;
        //    }
        //    set
        //    {
        //        _tableCollection = value;
        //        RaisePropertyChanged();
        //    }
        //}


        public CustomTable()
        {
            Main = new ObservableCollection<DataTable>
            {
                someRandomTable()
            };

            //TableCollection = new ContentControl();
            //TableCollection.Content = Main;
        }

        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);
            table.Rows.Add(53, "ACC", "Foobar", DateTime.Now);
            return table;
        }
    }
        </ScrollViewer.Resources>

        <ContentControl Content="{Binding}"/>

    </ScrollViewer>

结果:

  1. 这不是你需要的结果,但已经是“前进”了。 每个 ItemsControl 行应显示一个单独的 DataTable。 为了正确的测试,您需要在 Main 中至少放置几个 DataTable。
        public CustomTable()
        {
            Main = new ObservableCollection<DataTable>
            {
                someRandomTable(),
                someRandomTable()
            };
        }

结果:

  1. 我无法完全理解
    CustomTable.SelectedItem
    属性的含义。根据 XAML,
    Main
    属性的表之一中的一行绑定到此属性。但是这样的表有很多,但是绑定的属性只有一个。如果所选行位于多个表中,您期望什么行为?

在大多数实现中,集合的属性和其中选择的元素是同一级别的属性。因此,如果没有您的额外澄清,我将无法给出适合您的准确答案。

  1. 我的实现选项基于我的猜测:
using System;
using System.Collections.ObjectModel;
using System.Data;

namespace Core2023.SO.niconice.InfiniteDataGrid
{
    public class CustomTable : BaseViewModel
    {
        public ObservableCollection<DataTable> Main { get; }

        private CustomTable? _child;
        public CustomTable? Child
        {
            get
            {
                return _child;
            }
            set
            {
                _child = value;
                RaisePropertyChanged();
            }
        }


        private DataRowView? _selectedItem;
        public DataRowView? SelectedItem
        {
            get
            {
                return _selectedItem;
            }
            set
            {
                _selectedItem = value;
                Child ??= new CustomTable();
                RaisePropertyChanged();
            }
        }

        public CustomTable()
        {
            Main = new ObservableCollection<DataTable>
            {
                someRandomTable(),
                someRandomTable()
            };
        }

        private static 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);
            table.Rows.Add(53, "ACC", "Foobar", DateTime.Now);
            return table;
        }
    }
}
<Window x:Class="Core2023.SO.niconice.InfiniteDataGrid.InfiniteDataGridWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Core2023.SO.niconice.InfiniteDataGrid"
        mc:Ignorable="d"
        Title="InfiniteDataGridWindow" Height="1000" Width="400">
    <Window.DataContext>
        <local:CustomTable/>
    </Window.DataContext>

    <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>
        <ScrollViewer.Resources>
            <DataTemplate DataType="{x:Type local:CustomTable}">
                <StackPanel>
                    <ItemsControl x:Name="Main_ItemsControl" ItemsSource="{Binding Path=Main}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <DataGrid SelectedItem="{Binding DataContext.SelectedItem, Mode=TwoWay, ElementName=Main_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}"/>

    </ScrollViewer>
</Window>

结果。
选择行之前:

在第一级选择一行后:

在第二级选择一行后:

© www.soinside.com 2019 - 2024. All rights reserved.