Я разрабатываю приложение WPF и создал две сетки данных, как показано на прикрепленном изображении. Вторая сетка данных создается динамически с помощью метода CreateCoachCompositionDataGrid(). Существует еще один метод под названием UpdateCoachCompositionDataGrid(), который используется для обновления пользовательского интерфейса сетки данных (цвет фона ячеек, включение/отключение поля со списком и т. д.) на основе события SelectionChanged dataGridTrainHome (первая сетка данных). ).
Проблема, с которой я столкнулся, заключается в том, что пользовательский интерфейс сетки данных не обновляется, когда я выбираю строку из dataGridTrainHome. Однако я уверен, что метод UpdateCoachCompositionDataGrid() вызывается, поскольку обновляются метки (номер поезда, имя поезда, номер платформы).
Я не понимаю, в чем проблема.

Метод, который я использую для создания сетки данных:
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(), чтобы принудительно обновить пользовательский интерфейс сетки данных. Это не работает.
Я также попытался создать DataView из DataTable, а затем обновить пользовательский интерфейс сетки данных. Но это тоже ничего не изменило.
хорошо, я проверяю ваш код, это потому, что если ( stackPanel != null ) этот stackPanel всегда имеет значение null, потому что вы конвертируете ContentPresenter в StackPanel. Так что ничего не изменится, потому что оно никогда не попадает внутрь, если это утверждение, пожалуйста, дайте мне знать, если это поможет
Это выглядит немного странно. Я не думаю, что вам нужно обрабатывать какие-либо элементы пользовательского интерфейса в вашем сценарии. это только усложняет проблему. Почему бы вам не использовать DataTable? Вы можете добавить столбцы метаданных в таблицу и использовать ее, например. скройте ComboBox из шаблона ячейки, определенного в XAML. Это приведет к уменьшению враждебного кода.
@Каспар, спасибо за вклад! Я вижу, что моя stackPanel всегда равна нулю, поэтому сетка данных не обновляется. Не могли бы вы рассказать мне, как изменить мой код, чтобы он работал? Я новичок в этом и буду очень признателен за любую помощь, которую смогу получить!





Проблема в том, что:
StackPanel stackPanel = cellContent as StackPanel всегда имеет значение null, потому что cellContent возвращает ContentPresenter
вы можете легко изменить часть кода, чтобы просмотреть визуальное дерево:
var stackPanel =VisualTreeHelper.GetChild(cellContent, 0) as StackPanel;
Ноль означает, что ищем первого ребенка.
Это не очень стабильное решение, поскольку если вы измените StackPanel на другой макет, система выйдет из строя.
Я бы рекомендовал использовать DataTable и более поздние версии MVVM, которые легко обновляют состояние сеток.
Меня устраивает.
это входит в них, если для тренеров.констианс? или в этом примере каждый раз переходит к оператору else и устанавливает для поля со списком значение false?