WPF - Как получить ячейку из DataGridRow?
У меня есть DataGrid с привязкой к данным с чередующимися цветами фона строки. Я хотел бы покрасить ячейку по-разному в зависимости от данных, которые она содержит. Я пробовал решение, предлагаемое этой темой
http://wpf.codeplex.com/Thread/View.aspx?ThreadId=51143
Но,
DataGridCellsPresenter Presenter = GetVisualChild(строка)
всегда возвращает ноль.
я использую
public static T GetVisualChild<T>(Visual parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
Но VisualTreeHelper.GetChildrenCount() объекта DataGridRow всегда возвращает 0. Я проверил, что DataGridRow не является нулевым и уже заполнен данными. Любая помощь приветствуется.
Благодарю.
2 ответа
Если вы знаете свою строку и индекс ячейки, к которой хотите получить доступ, то вот как вы можете сделать это в коде:
//here's usage
var cell = myDataGrid.GetCell(row, columnIndex);
if(cell != null)
cell.Background = Brushes.Green;
Расширение DataGrid:
public static class DataGridExtensions
{
public static DataGridCell GetCell(this DataGrid grid, DataGridRow row, int columnIndex = 0)
{
if (row == null) return null;
var presenter = row.FindVisualChild<DataGridCellsPresenter>();
if (presenter == null) return null;
var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
if (cell != null) return cell;
// now try to bring into view and retreive the cell
grid.ScrollIntoView(row, grid.Columns[columnIndex]);
cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
return cell;
}
Прежде всего, не делайте этого в коде позади. Вы боретесь с рамками таким способом. WPF разработан по-другому; Вы должны думать о том, как структура хочет, чтобы вы что-то делали. В случае WPF это классы разметки XAML + конвертер.
Вам нужно две вещи, чтобы достичь того, что вы хотите:
- Правильная разметка XAML для настройки стиля DataGrid
- Реализация IValueConverter для перевода значения текста в правильный цвет выделения.
Вот оно:
XAML в вашей датагрид
Первое, что вы хотите сделать, это определить XAML, необходимый для стилизации ваших ячеек DataGrid. Это выглядит так:
<toolkit:DataGrid.CellStyle>
<Style TargetType="{x:Type toolkit:DataGridCell}">
<Style.Setters>
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text, Converter={StaticResource dataGridCellConverter}}" />
</Style.Setters>
</Style>
</toolkit:DataGrid.CellStyle>
То, что это делает, это устанавливает привязку к RelativeSource (DataGridCell) и говорит ему использовать Content.Text ячейки в качестве значения для передачи в Converter (dataGridCellConverter).
IValueConverter
Следующее, что вам нужно, это реализация IValueConverter, которая фактически определяет цвета на основе текста ячейки:
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace UserControls.Utility.Converters
{
public class DataGridCellConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return Colors.White.ToString();
if (value.ToString().ToUpper().Contains("CMS")) return "LIME";
return "ORANGE";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Здесь я просто ищу текст "CMS" и окрашиваю фоновую ячейку; если "CMS" не существует, он возвращает оранжевый цвет.
Укажите ресурсы
Теперь вам нужно добавить разметку в вашем окне /usercontrol, чтобы указать конвертер как соответствующий ресурс:
<UserControl.Resources>
<Converters:DataGridCellConverter x:Key="dataGridCellConverter"/>
</UserControl.Resources>
И это должно сделать это! Удачи.