Получить datagridcell по значению

У меня есть datagrid, который привязан к datatable, каждая ячейка имеет уникальное значение, поэтому никакие две ячейки не имеют одинакового значения.

Я хочу изменить ячейку со значением 1 (int32) на зеленый цвет. Обратите внимание, что значение 1 является динамическим, это просто пример, оно может находиться в диапазоне от 1 до 90.

Я поискал, и большая часть справки дает вам значение либо ячейки на основе ее координат, то есть (4,2), либо выбранной ячейки. Это не то, что я хочу, я хочу изменить цвет ячейки в зависимости от ее значения.

Есть ли способ сделать это, например, в JavaScript я бы просто назначил каждой ячейке идентификатор, эквивалентный ее значению, а затем что-то вроде $('#' + 1).css('background-color:green;') (примечание: это может быть неправильный синтаксис, но вы получаете изображение). Есть ли способ сделать это так же просто или стандартный?

Моя сетка данных

<DataGrid Name="grid" ItemsSource="{Binding}" Height="300" Width="900"
          AutoGenerateColumns="True"
          VerticalScrollBarVisibility="Disabled" HorizontalAlignment="Center" VerticalAlignment="Top" RowHeight="40">
            <DataGrid.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel Orientation="Vertical" />
                </ItemsPanelTemplate>
            </DataGrid.ItemsPanel>
        </DataGrid>

Создание таблицы

DataSet dataSet = new DataSet("myDS");
            DataTable numbersTable = new DataTable("Numbers");
            numbersTable.Columns.Add("Number", typeof(Int32));
            for (int i = 1; i < 91; i++)
            {
                numbersTable.Rows.Add(i);
            }
            dataSet.Tables.Add(numbersTable);
            grid.DataContext = numbersTable.DefaultView;

person RSM    schedule 22.11.2013    source источник
comment
Вы пытались найти желаемое значение, перебирая каждую (foreach) строку таблицы данных? Я имею в виду найти координаты ячейки с желаемым значением, а затем применить стиль или что-то еще ... Просто предложение.   -  person Asad Malik    schedule 27.11.2013
comment
Не могли бы вы сформулировать это как ответ и посмотреть, поможет ли это?   -  person RSM    schedule 28.11.2013


Ответы (3)


Есть несколько способов удовлетворить ваши требования. Это немного неудобно, потому что мы должны применять Style с Trigger к столбцам DataGrid, а не к самому DataGrid. Это означает, что вы не можете использовать функцию AutoGenerateColumns, и вам придется определять их все вручную, как показано ниже. Попробуй это:

<DataGrid ItemsSource="{Binding YourItems}" AutoGenerateColumns="False">
    <DataGrid.Resources>
        <Style x:Key="BackgroundColourStyle" TargetType="{x:Type TextBlock}">
            <Style.Triggers>
                <Trigger Property="Text" Value="1">
                    <Setter Property="Background" Value="LightGreen" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding YourPropertyName}" 
            ElementStyle="{StaticResource BackgroundColourStyle}">
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

ОБНОВЛЕНИЕ >>>

Хорошо, поэтому, чтобы сделать это со значением переменной, лучше сделать это WPF-ориентированным способом. Как обычно в WPF, мы хотим создавать объекты данных со всеми свойствами, которые нам нужно отображать в пользовательском интерфейсе. Таким образом, вам нужно будет добавить новое свойство bool в любой класс типа данных, который вы показываете в _8 _..., возможно, добавьте для этого новый столбец, если вы настаиваете на использовании DataTable.

Однако я бы посоветовал вам использовать класс, и если вы его создаете, вы должны убедиться, что вы правильно реализуете в нем интерфейс INotifyPropertyChanged. Вы можете добавить в него такие свойства:

public int NumberValue { get; set; } // implement `INotifyPropertyChanged` here
public bool HasHighlightValue { get; set; } // implement `INotifyPropertyChanged` here

Затем мы могли бы использовать это свойство, чтобы выделить соответствующую ячейку в DataGrid:

<Style x:Key="BackgroundColourStyle" TargetType="{x:Type TextBlock}">
    <Style.Triggers>
        <Trigger Property="HasHighlightValue" Value="True">
            <Setter Property="Background" Value="LightGreen" />
        </Trigger>
    </Style.Triggers>
</Style>

Наконец, вы можете установить это новое свойство в обработчике или коде в ответ на какое-либо действие пользователя:

// reset previous cell value
YourDataType previousItem = YourItems.Where(I => i.HasHighlightValue).Single();
previousItem.HasHighlightValue = false;
// set new cell value
YourDataType item = YourItems.Where(I => i.NumberValue == relevantNumber).Single();
item.HasHighlightValue = true;
person Sheridan    schedule 22.11.2013
comment
Я ищу динамическое решение, и значение было просто примером, это могло быть любое значение - person RSM; 22.11.2013
comment
Что означает динамическое решение? - person Sheridan; 22.11.2013
comment
что-то, что работает для любых требуемых мной ценностей, которые могут быть неопределенными для меня. - person RSM; 25.11.2013
comment
Вместо того, чтобы использовать такой код, не лучше ли было бы использовать комбинацию преобразователя + DataTrigger? - person Maverik; 25.11.2013
comment
@franssu, поправьте меня, если я ошибаюсь, но вы кажется предполагаете, что я скопировал свой ответ из вопроса, на который вы ссылались, исключительно на основе Color, который я использовал в своем тесте проект. Лично я нахожу это довольно оскорбительным ... как будто я не мог придумать Trigger, не копируя его. Если это была ваша точка зрения, то спасибо ... большой вклад. Если это не ваша точка зрения, то что? - person Sheridan; 25.11.2013
comment
@Maverik, вы можете добавить свой ответ, демонстрирующий вашу точку зрения. - person Sheridan; 25.11.2013
comment
@Sheridan Примите мои извинения. Тем не менее, этот поток может заинтересовать OP: stackoverflow.com/questions/5549617/ - person franssu; 25.11.2013
comment
@ Шеридан, это был вопрос, чтобы знать, будет ли лучше. Вы уже проделали большую часть работы, и я не думаю, что будет справедливо копировать большую часть этого, чтобы показать другую точку зрения, тем более, что это вопрос щедрости. Вы заслуживаете награды за полноценный ответ. - person Maverik; 27.11.2013
comment
@Maverik, код, который я показал, будет работать так же хорошо в модели представления ... он не должен быть в коде позади. - person Sheridan; 27.11.2013
comment
Привет, сегодня проверим эту теорию. Дам тебе знать. Спасибо. - person RSM; 28.11.2013
comment
Кстати, просто дал вам баллы, потому что вы больше всего пытались помочь, на самом деле не понимали, о чем говорит любой из этих ответов. - person RSM; 03.12.2013

Взгляните на этот цвет ячеек DataGrid на основе значений

Public class NameToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string input = value as string;
        switch (input)
        {
            case "John":
                return Brushes.LightGreen;
            default:
                return DependencyProperty.UnsetValue;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Сетка:

<DataGridTextColumn Binding="{Binding Name}">
    <DataGridTextColumn.ElementStyle>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="Background" Value="{Binding Name, Converter={StaticResource NameToBrushConverter}}"/>
        </Style>
    </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

Кисти:

public string Name
{
    get { return _name; }
    set
    {
        if (_name != value)
        {
            _name = value;
            OnPropertyChanged("Name");
            OnPropertyChanged("NameBrush");
        }
    }
}

public Brush NameBrush
{
    get
    {
        switch (Name)
        {
            case "John":
                return Brushes.LightGreen;
        }

        return Brushes.Transparent;
    }
}
person Mohamed Rozza    schedule 02.12.2013

Существует также следующий способ, который вы можете использовать для динамического форматирования DataGridCell при изменении его значения, используя событие Binding.TargetUpdated или Binding.SourceUpdated в DataGridCell.

Для этого необходимо сделать следующее:

  • Добавьте обработчик событий для события AutoGeneratingColumn в DataGrid. Например:

<DataGrid ItemsSource="{Binding}" AutoGeneratingColumn="OnAutoGeneratingColumn"/>

  • В обработчике AutoGeneratingColumn определите, имеет ли автоматически созданный столбец Binding, и если да, установите для него NotifyOnTargetUpdated значение true и установите CellStyle в столбце, который будет включать EventSetter для события Binding.TargetUpdatedEvent. Например:

    void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        BindingBase bindingBase = null;
    
        var dataGridBoundColumn = e.Column as DataGridBoundColumn;
        if (dataGridBoundColumn != null)
        {
            bindingBase = dataGridBoundColumn.Binding;
        }
        else
        {
            var dataGridComboBoxColumn = e.Column as DataGridComboBoxColumn;
            if (dataGridComboBoxColumn != null)
                bindingBase = dataGridComboBoxColumn.SelectedItemBinding;
        }
    
        var binding = bindingBase as Binding;
        if (binding != null)
        {
            binding.NotifyOnTargetUpdated = true;
    
            e.Column.CellStyle = new Style(typeof(DataGridCell))
            {
                Setters = 
                {
                    new EventSetter(Binding.TargetUpdatedEvent, new EventHandler<DataTransferEventArgs>(OnDataGridCellBindingTargetUpdated))
                }
            };
        }
    }
    
  • Реализуйте собственную логику для форматирования DataGridCell при изменении значения в обработчике OnDataGridCellBindingTargetUpdated. Например:

    private static void OnDataGridCellBindingTargetUpdated(object sender, DataTransferEventArgs e)
    {
        var dataGridCell = (DataGridCell)sender;
    
        // Get context: column and item.
        var column = dataGridCell.Column;
        var item = dataGridCell.DataContext;
    
        // TODO: based on context, format DataGridCell instance.
    }
    
person Stipo    schedule 29.11.2013