none
C# WPF DataGrid раскраска строк(столбцов) и отдельных ячеек RRS feed

  • Вопрос

  • Здравствуйте. Интересует такой вопрос - как в DataGrid раскрасить строку(столбец) или отдельные ячейки, но не в зависимости от значения(содержания), а от индексов? 

Ответы

  • Добрый день.

    Для создания раскраски через строку, вы можете воспользоваться свойством AlternatingRowBackground.

    Ну а для столбцов, можно сделать вот так:

    <DataGrid>
        <DataGrid.Resources>
            <Style TargetType="DataGridCell" x:Key="greenCell">
                <Setter Property="Background" Value="Green" />
            </Style>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Header="1111" />
            <DataGridTextColumn Header="1111" CellStyle="{StaticResource greenCell}" />
        </DataGrid.Columns>
    </DataGrid>

    • Помечено в качестве ответа GwBlaize 15 мая 2014 г. 8:16
    Отвечающий
  • Вот, совсем другое дело.

    Добавляете для значений в таблице класс обертку. Например, вот такой:

    class NumberWrapper : DependencyObject
    {
        /// <summary>
        /// Значение
        /// </summary>
        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
    
        /// <summary>
        /// Static part of dependency property Value
        /// </summary>
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(NumberWrapper), new UIPropertyMetadata(0d));
    
        /// <summary>
        /// Врзвращает true, если вбранный элемент является ведущим
        /// </summary>
        public bool IsPivotalEntry
        {
            get { return (bool)GetValue(IsPivotalEntryProperty); }
            set { SetValue(IsPivotalEntryProperty, value); }
        }
    
        /// <summary>
        /// Static part of dependency property IsPivotalEntry
        /// </summary>
        public static readonly DependencyProperty IsPivotalEntryProperty =
            DependencyProperty.Register("IsPivotalEntry", typeof(bool), typeof(NumberWrapper), new UIPropertyMetadata(false));
    }

    Соответственно матрица у вас тоже будет не double, а элементов такого типа. Ну и небольшая демка, как этим воспользоваться.

    1. Добавляю класс конвертер в проект:

    class IsPivotalEntryToColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            SolidColorBrush result = null;
            if (value is bool && (bool)value)
            {
                result = new SolidColorBrush(Colors.LightGreen);
            }
            return result;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    2. На форму подключаю пространство имен, конвертор в качестве ресурса, кидаю Grid, настраиваю столбцы. Ну и две кнопки для демки:

    <Window x:Class="WpfApplication9.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfApplication9"
            Title="MainWindow" Height="198" Width="393">
        <Grid>
            <DataGrid x:Name="dgMain" HorizontalAlignment="Left" Height="145" Margin="10,10,0,0" VerticalAlignment="Top" Width="181" AutoGenerateColumns="False">
                <DataGrid.Resources>
                    <local:IsPivotalEntryToColorConverter x:Key="IsPivotalEntryToColorConverter" />
                </DataGrid.Resources>
                <DataGrid.Columns>
                    <DataGridTemplateColumn Header="1">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Grid Background="{Binding [0].IsPivotalEntry,Converter={StaticResource IsPivotalEntryToColorConverter}}">
                                    <TextBlock Text="{Binding [0].Value}" />
                                </Grid>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn Header="2">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Grid Background="{Binding [1].IsPivotalEntry,Converter={StaticResource IsPivotalEntryToColorConverter}}">
                                    <TextBlock Text="{Binding [1].Value}" />
                                </Grid>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
            <Button Content="Заполнить матрицу" HorizontalAlignment="Left" Margin="225,19,0,0" VerticalAlignment="Top" Width="133" Click="Button_Click"/>
            <Button Content="Найти ведущий элемент" HorizontalAlignment="Left" Margin="225,44,0,0" VerticalAlignment="Top" Width="133" Click="Button_Click_1"/>
        </Grid>
    </Window>

    3. Методы для заполнения и "выбора ведущего элемента":

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    
        ObservableCollection<ObservableCollection<NumberWrapper>> data = null;
    
        Random rnd = new Random(DateTime.Now.Millisecond);
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            data = new ObservableCollection<ObservableCollection<NumberWrapper>>();            
            for (int i = 0; i < 5; i++)
            {
                ObservableCollection<NumberWrapper> temp = new ObservableCollection<NumberWrapper>();
                for (int j = 0; j < 2; j++)
                {
                    temp.Add(new NumberWrapper() { Value = Math.Round(rnd.NextDouble() * 100 - 50, 2), IsPivotalEntry = false });
                }
                data.Add(temp);
            }
            dgMain.ItemsSource = data;
        }
    
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            data[rnd.Next(5)][rnd.Next(2)].IsPivotalEntry = true;
        }
    }

    Вот так все это работает:

    • Помечено в качестве ответа GwBlaize 19 мая 2014 г. 11:35
    Отвечающий

Все ответы

  • Добрый день.

    Для создания раскраски через строку, вы можете воспользоваться свойством AlternatingRowBackground.

    Ну а для столбцов, можно сделать вот так:

    <DataGrid>
        <DataGrid.Resources>
            <Style TargetType="DataGridCell" x:Key="greenCell">
                <Setter Property="Background" Value="Green" />
            </Style>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Header="1111" />
            <DataGridTextColumn Header="1111" CellStyle="{StaticResource greenCell}" />
        </DataGrid.Columns>
    </DataGrid>

    • Помечено в качестве ответа GwBlaize 15 мая 2014 г. 8:16
    Отвечающий
  • Алексей, а вы не подскажите, как сделать то же самое с отдельной ячейкой?
  • Не очень понял вопрос. Вы хотите какую-то конкретную ячейку выделять? Или в зависимости от данных которые в ней показываются?
    Отвечающий
  • Конкретную ячейку, вне зависимости от содержимого
  • Как вы определяете какую ячейку надо красить?

    Отвечающий
  • Допустим, на пересечении определенного столбца и строки
  • Очень лень тратить время на решение задачи по построению сферического коня в вакууме. Напишите, какая конкретно задача перед вами стоит и я постараюсь помочь. Просто сделать другого цвета конкретно одну ячейку, например, с координатами 2,3 (вне привязки к данным) достаточно проблематично. Это и данные показываемые в гриде придется предварительно готовить и конверторы добавлять... Лучше опишите в чем состоит именно ваша задача.
    Отвечающий
  • Такс, задача конкретно вот какая - реализовать программно симплекс метод решения задачи линейного программирования, в частности - метод искусственного базиса. Также должен быть реализован режим решения, как говорится, вручную. В процессе пользователю необходимо самому выбирать ведущий элемент в таблице, их может быть несколько. Вот скажем "для удобства" пользователя элементы, которые могут быть ведущими на данном шаге перерасчета симплекс таблицы, должны быть подсвечены, раскрашены в другой цвет. В данной задаче даже не представляю как исходя из содержимого можно раскрасить необходимые ячейки, это ведь, к примеру, есть несколько отрицательных коэффициентов, которые определяют ведущий столбец, далее в каждом таком столбце выбирается минимальный элемент, определяющий ведущую строку, цель - раскрасит ячейку на их пересечении, ячейку с ведущим элементом. 
  • Вот, совсем другое дело.

    Добавляете для значений в таблице класс обертку. Например, вот такой:

    class NumberWrapper : DependencyObject
    {
        /// <summary>
        /// Значение
        /// </summary>
        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
    
        /// <summary>
        /// Static part of dependency property Value
        /// </summary>
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(NumberWrapper), new UIPropertyMetadata(0d));
    
        /// <summary>
        /// Врзвращает true, если вбранный элемент является ведущим
        /// </summary>
        public bool IsPivotalEntry
        {
            get { return (bool)GetValue(IsPivotalEntryProperty); }
            set { SetValue(IsPivotalEntryProperty, value); }
        }
    
        /// <summary>
        /// Static part of dependency property IsPivotalEntry
        /// </summary>
        public static readonly DependencyProperty IsPivotalEntryProperty =
            DependencyProperty.Register("IsPivotalEntry", typeof(bool), typeof(NumberWrapper), new UIPropertyMetadata(false));
    }

    Соответственно матрица у вас тоже будет не double, а элементов такого типа. Ну и небольшая демка, как этим воспользоваться.

    1. Добавляю класс конвертер в проект:

    class IsPivotalEntryToColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            SolidColorBrush result = null;
            if (value is bool && (bool)value)
            {
                result = new SolidColorBrush(Colors.LightGreen);
            }
            return result;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    2. На форму подключаю пространство имен, конвертор в качестве ресурса, кидаю Grid, настраиваю столбцы. Ну и две кнопки для демки:

    <Window x:Class="WpfApplication9.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfApplication9"
            Title="MainWindow" Height="198" Width="393">
        <Grid>
            <DataGrid x:Name="dgMain" HorizontalAlignment="Left" Height="145" Margin="10,10,0,0" VerticalAlignment="Top" Width="181" AutoGenerateColumns="False">
                <DataGrid.Resources>
                    <local:IsPivotalEntryToColorConverter x:Key="IsPivotalEntryToColorConverter" />
                </DataGrid.Resources>
                <DataGrid.Columns>
                    <DataGridTemplateColumn Header="1">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Grid Background="{Binding [0].IsPivotalEntry,Converter={StaticResource IsPivotalEntryToColorConverter}}">
                                    <TextBlock Text="{Binding [0].Value}" />
                                </Grid>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn Header="2">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Grid Background="{Binding [1].IsPivotalEntry,Converter={StaticResource IsPivotalEntryToColorConverter}}">
                                    <TextBlock Text="{Binding [1].Value}" />
                                </Grid>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
            <Button Content="Заполнить матрицу" HorizontalAlignment="Left" Margin="225,19,0,0" VerticalAlignment="Top" Width="133" Click="Button_Click"/>
            <Button Content="Найти ведущий элемент" HorizontalAlignment="Left" Margin="225,44,0,0" VerticalAlignment="Top" Width="133" Click="Button_Click_1"/>
        </Grid>
    </Window>

    3. Методы для заполнения и "выбора ведущего элемента":

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    
        ObservableCollection<ObservableCollection<NumberWrapper>> data = null;
    
        Random rnd = new Random(DateTime.Now.Millisecond);
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            data = new ObservableCollection<ObservableCollection<NumberWrapper>>();            
            for (int i = 0; i < 5; i++)
            {
                ObservableCollection<NumberWrapper> temp = new ObservableCollection<NumberWrapper>();
                for (int j = 0; j < 2; j++)
                {
                    temp.Add(new NumberWrapper() { Value = Math.Round(rnd.NextDouble() * 100 - 50, 2), IsPivotalEntry = false });
                }
                data.Add(temp);
            }
            dgMain.ItemsSource = data;
        }
    
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            data[rnd.Next(5)][rnd.Next(2)].IsPivotalEntry = true;
        }
    }

    Вот так все это работает:

    • Помечено в качестве ответа GwBlaize 19 мая 2014 г. 11:35
    Отвечающий
  • Спасибо огромное, выручили!
  • Да не за что. Обращайтесь.

    P.s. На будущее, если обсуждение выходит за рамки первоначального опроса, то лучше ветку закрывать и создавать новую. Так искать ответы новым участникам форума будет значительно легче.

    Отвечающий