【问题标题】:Create multiple DataGrids in WPF dynamically在 WPF 中动态创建多个 DataGrid
【发布时间】:2020-12-16 13:16:17
【问题描述】:

我正在尝试在 WPF 中动态创建 DataGrids,在 Grid 中一个低于另一个。问题是我什至不知道从哪里开始,我看到可以通过代码完成,但我想正确使用 XAML。

void PopulateDatagridSQL(string Data, string index, string TabName)
{
   try
   {
      Data = Data.Replace((Char)6, (Char)124);

      List<DataTable> Results = new List<DataTable>();

      Results = JsonConvert.DeserializeObject<List<DataTable>>(Data);
      foreach (SQLWindow SingleSQLWindows in StaticVar.MySQLWindows)
      {
         if (SingleSQLWindows.MyINDEX == index)
         {
            SingleSQLWindows.Dispatcher.Invoke(new Action(() =>
            {
               foreach (TabItem item in SingleSQLWindows._tabItems)
               {
                  if (item.Name == TabName)
                  {
                     //create multiple datagrids up to results.count
                     ((SQLPage)((Frame)item.Content).Content).DataGrid1.ItemsSource = Results[0].DefaultView;//foreach
                     ((SQLPage)((Frame)item.Content).Content).TxtSqlLog.Text = "Records in Datagrid: " + Results[0].Rows.Count;//foreach
                  }
               }
            }));
         }
      }
   }
   catch (Exception asd)
   {

      foreach (SQLWindow SingleSQLWindows in StaticVar.MySQLWindows)
      {
         if (SingleSQLWindows.MyINDEX == index)
         {
            SingleSQLWindows.Dispatcher.Invoke(new Action(() =>
            {
               foreach (TabItem item in SingleSQLWindows._tabItems)
               {
                  if (item.Name == TabName)
                  {
                     ((SQLPage)((Frame)item.Content).Content).TxtSqlLog.Text = "Error in $SqlResponse";
                  }
               }
            }));
         }
      }
   }
}

在这个函数中,我收到DataTables 的列表,对于每个DataTable,我必须创建一个DataGrid

<Page x:Class="Emergency_APP_Server_WPF.Forms.SQLPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:local="clr-namespace:Emergency_APP_Server_WPF.Forms"
  mc:Ignorable="d" x:Name="SQLPageXaml" Loaded="SQLPage_Loaded"
  d:DesignHeight="450" d:DesignWidth="800"
  Title="SQLPage" >

<Grid>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" MinHeight="100"></RowDefinition>
            <RowDefinition Height="0"></RowDefinition>
            <RowDefinition Height="*" MinHeight="150"></RowDefinition>
            <RowDefinition Height="35"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition Width="70"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <avalonEdit:TextEditor Grid.Column="0" Background="White"
            xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"  
            Name="MyAvalonEdit" FontFamily="Consolas"
            FontSize="11pt" Margin="10,10,10,10" ShowLineNumbers="True"
            LineNumbersForeground="Gray" ScrollViewer.VerticalScrollBarVisibility="Auto"
            ScrollViewer.HorizontalScrollBarVisibility="Auto" KeyUp="MyAvalonEdit_KeyUp"/>
            <Button  Grid.Column="1" x:Name="BtnSendSQL" Margin="0,10,10,10" Click="BtnSendSQL_Click">
                <StackPanel>
                    <Image Height="25" Source="..//Resources/send.png"></Image>
                    <TextBlock Margin="0,10,0,0" VerticalAlignment="Top" Foreground="White" Text="SendSQL"></TextBlock>
                </StackPanel>
            </Button>
        </Grid>
        <GridSplitter Margin="0,-10,0,0" Grid.Row="1" HorizontalAlignment="Stretch" Background="Transparent" ResizeBehavior="PreviousAndNext">
        </GridSplitter>
        <DataGrid Grid.Row="2" x:Name="DataGrid1" RowStyle="{StaticResource DataGridRowSql}" Style="{StaticResource DataGridStyleSQL}" >
            <DataGrid.CommandBindings>
                <CommandBinding Command="Copy" Executed="CommandBinding_Executed"></CommandBinding>
            </DataGrid.CommandBindings>
            <DataGrid.InputBindings>
                <KeyBinding Key="C" Modifiers="Ctrl" Command="Copy"></KeyBinding>
            </DataGrid.InputBindings>
        </DataGrid>
        <TextBlock TextAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Bottom" Grid.Row="3" x:Name="TxtSqlLog" Text="Wait For Commands..."
                   FontSize="14" FontFamily="Consolas" Foreground="White"></TextBlock>
    </Grid>
</Grid>

【问题讨论】:

    标签: c# sql wpf xaml datagrid


    【解决方案1】:

    我不知道你想把所有DataGrids 放在哪里的确切布局,所以我只是假设你想把它们放在22 行中。如果您想堆叠它们,您可以在ScrollViewer 中使用ItemsControl。后者就在那里,因此您可以滚动浏览DataGrids,以防页面太小而无法全部显示。所以这是下面解决方案的基本布局。

    <Grid>
       <Grid.RowDefinitions>
          <!-- ...your row definitions. -->
       </Grid.RowDefinitions>
       <!-- ...your other controls. -->
       <ScrollViewer Grid.Row="2">
          <ItemsControl/>
       </ScrollViewer>
    </Grid>
    

    代码隐藏解决方案

    在代码隐藏中,您需要访问ItemsControl,因此为其指定一个名称。

    <ItemsControl x:Name="DataGridContainer"/>
    

    然后从您的DataTable 列表中循环创建DataGrids。

    foreach (var dataTable in Results)
    {
       var dataGrid = new DataGrid { ItemsSource = dataTable.DefaultView };
       DataGridContainer.Items.Add(dataGrid);
    };
    

    顺便说一句,在这种情况下,您还可以使用StackPanel 而不是ItemsControl

    MVVM 解决方案

    您可以在您的视图模型中创建一个属性,以公开您的DataTables 的默认视图。

    public ObservableCollection<DataView> DataViews { get; }
    

    确保在构造函数中实例化集合或实现INotifyPropertyChanged,以便集合在 XAML 中可用。然后将ItemsControl 绑定到这个集合。

    <ItemsControl ItemsSource="{Binding DataViews}"/>
    

    接下来为DataView 类型创建一个DataTemplate。由于绑定集合中的每个数据视图都代表一个应显示为DataGrid 的数据表,因此它看起来像这样。

    <DataTemplate DataType="{x:Type data:DataView}">
       <DataGrid ItemsSource="{Binding}"/>
    </DataTemplate>
    

    然后您必须在ItemsControl 中将此数据模板分配为ItemTemplate。我只是在这里内联,但你也可以将它放在任何ResourceDictionary 中并通过StaticResource 引用它。

    <ItemsControl ItemsSource="{Binding DataViews}">
       <ItemsControl.ItemTemplate>
          <DataTemplate DataType="{x:Type data:DataView}">
             <DataGrid ItemsSource="{Binding}"/>
          </DataTemplate>
       </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    现在,您只需将默认视图添加到 DataViews 集合。由于此集合是一个ObservableCollection,它会通知ItemsControl 在每次添加时更新。

    foreach (var dataTable in Results)
    {
       DataViews.Add(dataTable.DefaultView);
    };
    

    添加项目时,ItemsControl 将收到通知并使用 DataTemplate 创建项目。

    我建议您使用 MVVM 解决方案,因为它将演示文稿与您的数据分开,并且更容易实现,并且通过 DataTemplate 自定义 DataGrids 在 XAML 中更容易、方便和可维护。

    【讨论】:

    • 我有问题:(
    【解决方案2】:
    <Page x:Class="Emergency_APP_Server_WPF.Forms.SQLPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:z="clr-namespace:System.Data;assembly=System.Data"
      xmlns:local="clr-namespace:Emergency_APP_Server_WPF.Forms"
      mc:Ignorable="d" x:Name="SQLPageXaml" Loaded="SQLPage_Loaded"
      d:DesignHeight="450" d:DesignWidth="800"
      Title="SQLPage" >
    
    <Grid>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" MinHeight="100"></RowDefinition>
                <RowDefinition Height="0"></RowDefinition>
                <RowDefinition Height="*" MinHeight="150"></RowDefinition>
                <RowDefinition Height="35"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition Width="70"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <avalonEdit:TextEditor Grid.Column="0" Background="White"
                xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"  
                Name="MyAvalonEdit" FontFamily="Consolas"
                FontSize="11pt" Margin="10,10,10,10" ShowLineNumbers="True"
                LineNumbersForeground="Gray" ScrollViewer.VerticalScrollBarVisibility="Auto"
                ScrollViewer.HorizontalScrollBarVisibility="Auto" KeyUp="MyAvalonEdit_KeyUp"/>
                <Button  Grid.Column="1" x:Name="BtnSendSQL" Margin="0,10,10,10" Click="BtnSendSQL_Click">
                    <StackPanel>
                        <Image Height="25" Source="..//Resources/send.png"></Image>
                        <TextBlock Margin="0,10,0,0" VerticalAlignment="Top" Foreground="White" Text="SendSQL"></TextBlock>
                    </StackPanel>
                </Button>
            </Grid>
            <GridSplitter Margin="0,-10,0,0" Grid.Row="1" HorizontalAlignment="Stretch" Background="Transparent" ResizeBehavior="PreviousAndNext">
            </GridSplitter>
    
            <ScrollViewer Grid.Row="2">
                <ItemsControl ItemsSource="{Binding DataViews}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate DataType="{x:Type z:DataView}">
                            <DataGrid RowStyle="{StaticResource DataGridRowSql}" Style="{StaticResource DataGridStyleSQL}" ItemsSource="{Binding}">
                                <DataGrid.CommandBindings>
                                    <CommandBinding Command="Copy" Executed="CommandBinding_Executed"></CommandBinding>
                                </DataGrid.CommandBindings>
                                <DataGrid.InputBindings>
                                    <KeyBinding Key="C" Modifiers="Ctrl" Command="Copy"></KeyBinding>
                                </DataGrid.InputBindings>
                            </DataGrid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </ScrollViewer>
            <TextBlock TextAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Bottom" Grid.Row="3" x:Name="TxtSqlLog" Text="Wait For Commands..."
                       FontSize="14" FontFamily="Consolas" Foreground="White"></TextBlock>
        </Grid>
    </Grid>
    
     public ObservableCollection<DataView> _DataViews = new ObservableCollection<DataView>();
        public ObservableCollection<DataView> DataViews
        {
            get
            {
                return _DataViews;
            }
            set
            {
                _DataViews = value;
                OnPropertyChanged();
            }
    
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected void OnPropertyChanged([CallerMemberName] string Param = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(Param));
        }
    
    
    foreach (SQLWindow SingleSQLWindows in StaticVar.MySQLWindows)
                {
                    if (SingleSQLWindows.MyINDEX == index)
                    {
                        SingleSQLWindows.Dispatcher.Invoke(new Action(() =>
                        {
                            foreach (TabItem item in SingleSQLWindows._tabItems)
                            {
                                if (item.Name == TabName)
                                {
                                    foreach (DataTable itemTable in Results)
                                    {
                                        //SingleSQLWindows.DataViews.Add(itemTable.DefaultView);
    
                                        ////create more datagrid while results.count
                                        ///
                                        ((SQLPage)((Frame)item.Content).Content).DataViews.Add(itemTable.DefaultView);
                                        //((SQLPage)((Frame)item.Content).Content).TxtSqlLog.Text = "Records in Datagrid: " + Results[0].Rows.Count;//foreach
                                    }
    
    
    
                                }
                            }
                        }));
                    }
                }
    

    Visual Studio 没有报告任何错误,但滚动查看器仍然为空,我不明白为什么

    【讨论】:

    • 之前有没有用过,还是根本没用过?请在运行时检查 DataViews 集合是否有任何项目,例如填充列表后添加断点。如果有任何绑定错误,请检查您的输出。我不确定您是否在((SQLPage)((Frame)item.Content).Content).DataViews.Add(itemTable.DefaultView); 这一行中正确添加到DataViews 集合中,它看起来很可疑。此外,您应用的样式可能会导致问题。也可以尝试不使用它们。
    • 从不工作,我认为它会工作 - 我删除 RowStyle="{StaticResource DataGridRowSql}" Style="{StaticResource DataGridStyleSQL}" 但什么都没有......在这个屏幕上你可以查看 DataViews 计数,我也尝试在返回 _DataViews 时停止;它停止了!然后代码通过那里。有什么建议吗?链接到图像数据视图IMAGE
    • 输出怎么样,是否显示绑定错误之类的错误?
    • 没有,只有空,没有错误:|见图片IMAGE
    • 尝试仅将ScrollViewer 及其控件放在网格中或Page 上,以查看是否由于布局错误而未显示。由于没有绑定错误并且填充了 DataViews 属性,因此它似乎没有显示出来。
    猜你喜欢
    • 2013-10-22
    • 2011-11-13
    • 1970-01-01
    • 2013-06-08
    • 2011-03-05
    • 2011-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多