更新 WPF 中动态创建的 DataGrid

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

我正在开发一个 WPF 应用程序,并创建了两个数据网格,如附图所示。第二个数据网格是使用 CreateCoachCompositionDataGrid() 方法动态创建的。还有另一个名为 UpdateCoachCompositionDataGrid() 方法,用于根据 dataGridTrainHome(第一个数据网格)的 SelectionChanged 事件更新数据网格的 UI(单元格的背景颜色、组合框启用/禁用等) ).

我一直面临的问题是,当我从 dataGridTrainHome 中选择一行时,数据网格的 UI 没有更新。但是,我确信 UpdateCoachCompositionDataGrid() 方法正在被调用,因为标签(火车编号、火车名称、站台编号)正在更新。

我不知道问题是什么。

Screenshot of the Window

我用来创建数据网格的方法:

private void CreateCoachCompositionDataGrid()
{
    // Clear the existing columns in the data grid
    dataGridCoachComposition.Columns.Clear();

    // Set the margin for the data grid
    dataGridCoachComposition.Margin = new Thickness(16, 468, 230, 18);

    // Hide the column headers
    dataGridCoachComposition.HeadersVisibility = DataGridHeadersVisibility.None;

    // Set the row height
    dataGridCoachComposition.RowHeight = 50; // Set this to your desired row height

    // Set the vertical alignment to top to remove empty space at the bottom
    dataGridCoachComposition.VerticalAlignment = VerticalAlignment.Top;

    // Create 14 columns
    for (int i = 1; i <= 14; i++)
    {
        // Create a new DataGridTemplateColumn
        DataGridTemplateColumn column = new DataGridTemplateColumn();
        column.Width = new DataGridLength(1, DataGridLengthUnitType.Star); // Set the column width to fill the available space

        // Create a DataTemplate for the cell template
        DataTemplate cellTemplate = new DataTemplate();

        // Create a StackPanel to hold the TextBlock and ComboBox
        FrameworkElementFactory stackPanel = new FrameworkElementFactory(typeof(StackPanel));
        stackPanel.SetValue(StackPanel.OrientationProperty, Orientation.Vertical);

        // Create a TextBlock for the coach number
        FrameworkElementFactory textBlock = new FrameworkElementFactory(typeof(TextBlock));
        textBlock.SetValue(TextBlock.TextProperty, "C" + i.ToString("00"));
        textBlock.SetValue(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Center); // Center the text block horizontally
        stackPanel.AppendChild(textBlock);

        // Create a ComboBox for the coach type
        FrameworkElementFactory comboBox = new FrameworkElementFactory(typeof(ComboBox));
        comboBox.SetValue(ComboBox.ItemsSourceProperty, new string[] { "ENG", "HIN" });
        comboBox.SetValue(FrameworkElement.MarginProperty, new Thickness(5)); // Set a margin around the ComboBox
        stackPanel.AppendChild(comboBox);

        // Set the cell template's visual tree to the StackPanel
        cellTemplate.VisualTree = stackPanel;

        // Set the column's cell template
        column.CellTemplate = cellTemplate;

        // Add the column to the data grid
        dataGridCoachComposition.Columns.Add(column);
    }

    // Add two empty rows to the data grid
    dataGridCoachComposition.Items.Add(new object());
    dataGridCoachComposition.Items.Add(new object());
}

我用来更新数据网格的方法:

private void UpdateCoachCompositionDataGrid(DataRow selectedRow)
{
    // Get the TrainNumber, TrainName, and PlatformNumber from the selected row
    string trainNumber = selectedRow["TrainNumber"].ToString();
    string trainName = selectedRow["TrainName"].ToString();
    string platformNumber = selectedRow["PlatformNumber"].ToString();

    // Display train information in the labels
    lblTrainNo.Content = "Train Number: " + trainNumber;
    lblTrainName.Content = "Train Name: " + trainName;
    lblPlatformNo.Content = "Platform Number: " + platformNumber;

    // Get the coach numbers from the database
    List<string> coachNumbers = GetCoachNumbersFromDatabase(trainNumber);

    // Iterate over each cell in the data grid
    for (int i = 0; i < dataGridCoachComposition.Columns.Count; i++)
    {
        for (int j = 0; j < dataGridCoachComposition.Items.Count; j++)
        {
            // Get the cell content
            var cellContent = dataGridCoachComposition.Columns[i].GetCellContent(dataGridCoachComposition.Items[j]);

            // Get the StackPanel in the cell
            StackPanel stackPanel = cellContent as StackPanel;

            if (stackPanel != null)
            {
                // Get the ComboBox in the StackPanel
                ComboBox comboBox = stackPanel.Children.OfType<ComboBox>().FirstOrDefault();

                if (comboBox != null)
                {
                    // Check if the coach number is present
                    if (coachNumbers.Contains("C" + (i + 1 + j * 14).ToString("00")))
                    {
                        // Auto-populate the ComboBox with 'ENG'
                        comboBox.SelectedIndex = 0;

                        // Enable the ComboBox
                        comboBox.IsEnabled = true;

                        // Set the cell background to white
                        ((DataGridCell)cellContent.Parent).Background = new SolidColorBrush(Colors.White);
                    }
                    else
                    {
                        // Clear the ComboBox selection
                        comboBox.SelectedIndex = -1;

                        // Disable the ComboBox
                        comboBox.IsEnabled = false;

                        // Set the cell background to grey
                        ((DataGridCell)cellContent.Parent).Background = new SolidColorBrush(Colors.Gray);
                    }
                }
            }
        }
    }
}

通过以下方式调用 UpdateCoachCompositionDataGrid():

private void dataGridTrainHome_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Get the currently selected items in the DataGrid
    var selectedRows = dataGridTrainHome.SelectedItems;

    // If any rows are selected
    if (selectedRows != null && selectedRows.Count > 0)
    {
        // Get the last selected row
        DataRowView lastSelectedRow = (DataRowView)selectedRows[selectedRows.Count - 1];

        // Use the Dispatcher to delay the call to UpdateCoachCompositionDataGrid
        Dispatcher.BeginInvoke(new Action(() =>
        {
            // Update the coach composition DataGrid
            UpdateCoachCompositionDataGrid(lastSelectedRow.Row);
        }), DispatcherPriority.Render);
    }
}

我尝试使用 dataGridCoachComposition.UpdateLayout() 强制更新数据网格的 UI。没成功。

我还尝试从 DataTable 创建 DataView,然后更新数据网格的 UI。但是,这也没有改变任何事情。

c# wpf data-binding datagrid
1个回答
0
投票

问题在于:

StackPanel stackPanel = cellContent as StackPanel
始终为 null,因为 cellContent 返回 ContentPresenter

您可以轻松更改代码部分以查看可视化树:

var stackPanel =VisualTreeHelper.GetChild(cellContent, 0) as StackPanel;

零表示寻找第一个孩子。

这不是非常稳定的解决方案,因为如果您将 StackPanel 更改为其他布局,系统将崩溃。

我建议使用 DataTable 和后来的 MVVM 来轻松更新网格状态。

它对我有用。

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