Изменение цвета фона ячеек, если значение больше или равно

#c# #wpf #xaml #data-binding #datagrid

Вопрос:

Я застрял на изменении цвета, если число в моем больше нуля DataGrid . Я пытался IValueConverter , но не могу заставить это работать. Это работает только в том случае, если я уже знаю значение в DataGrid . Это мой XAML. Зеленый цвет-это тот, который я могу заставить работать с кодом под ним. Я попытался связать его со IValueConverter своим .

 <DataGrid x:Name="dg_ProductlistGrid"  ItemsSource="{Binding ProductCollection}" AutoGenerateColumns="False" IsReadOnly="True" Loaded="form1_load">
       
    <DataGrid.ColumnHeaderStyle>
        <Style TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="BorderBrush" Value="Black"/>
            <Setter Property="BorderThickness" Value="1,1,1,1"/>
            <Setter Property="Padding" Value="30,9,12,6"/>
        </Style>
    </DataGrid.ColumnHeaderStyle>
        
    <DataGrid.Columns>
            
            <DataGridTextColumn Header="ProduktID" Binding="{Binding Path=factProduct.ProductId}" Width="*"  IsReadOnly="True"/>
        <DataGridTextColumn Header="Navn" Binding="{Binding Path= factProduct.Name}" Width="*"  IsReadOnly="True"/>
        <DataGridTextColumn Header="Mængde" Binding="{Binding Path =QauntityNeeded }" Width="*"  IsReadOnly="True"/>
        <DataGridTextColumn Header="Rigtige Mængde" Binding="{Binding Path =FoundQauntity }" Width="*"  IsReadOnly="True"/>
        <DataGridTextColumn Header="Mangel" Binding="{Binding Path = Missing}" Width="*"  IsReadOnly="True">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="{x:Type TextBlock}">
                    <Style.Triggers>
                        <Trigger Property="Text" Value="0">
                            <Setter Property="Background" Value="LightGreen"/>
                        </Trigger>
                        <Trigger Property="Text" >
                                <Setter Property="Background" Value="{Binding Path=Missing, Converter={StaticResource converter}}"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGridTextColumn.ElementStyle>
            </DataGridTextColumn>
 

Это мой IValueConverter :

 public class Greaterthan : IValueConverter
{
    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int input = (int)value;
        if (input < 1)
        {
            return new SolidColorBrush(Colors.Red);
        }
        else
            return DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
 

Как мне решить эту проблему?

Ответ №1:

Ваш конвертер проверяет не то, больше ли значение нуля, а то, меньше ли оно единицы. Вы можете упростить свой конвертер и в то же время сделать его более мощным. Ожидайте, что значение больше, чем значение параметра для преобразователя. Хотя вы можете указать int в XAML в качестве параметра, более удобно указывать значение в виде a string , как показано ниже при использовании конвертера. Этот преобразователь анализирует string значение и параметр as int и возвращает, больше ли значение параметра as bool .

 public class GreaterThanConverter : IValueConverter
{
   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
      if (!(value is string valueText) ||
          !(parameter is string parameterText) ||
          !int.TryParse(valueText, out var intValue) ||
          !int.TryParse(parameterText, out var intParameter))
         return Binding.DoNothing;

      return intValue > intParameter;
   }

   public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
   {
      throw new NotImplementedException();
   }
}
 

В XAML вы можете использовать a DataTrigger с привязкой к Text , которая использует конвертер. Если преобразователь возвращает true значение (то есть значение больше, чем параметр), устанавливается определенный цвет.

 <DataGridTextColumn.ElementStyle>
   <Style TargetType="{x:Type TextBlock}">
      <Style.Triggers>
         <Trigger Property="Text" Value="0">
            <Setter Property="Background" Value="LightGreen"/>
         </Trigger>
         <DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource GreaterThanConverter}, ConverterParameter=0}" Value="True">
            <Setter Property="Background" Value="Red"/>
         </DataTrigger>
      </Style.Triggers>
   </Style>
</DataGridTextColumn.ElementStyle>
 

Обязательно создайте экземпляр конвертера в любом словаре ресурсов, например , в DataGrid , в противном случае вы получите сообщение об ошибке, что ресурс не может быть разрешен.

 <DataGrid>
   <DataGrid.Resources>
      <local:GreaterThanConverter x:Key="GreaterThanConverter"/>
   </DataGrid.Resources>
   <!-- ...other markup. -->
</DataGrid>
 

Также убедитесь, что вы определили local пространство имен в файле XAML.

 xmlns:local="clr-namespace:MyWpfApp.MyNamespace"
 

Комментарии:

1. Ресурс «конвертер» не удалось решить, пару раз получал это с помощью разных вещей, которые я пытался реализовать, но, похоже, не могу понять, почему

2. @Gerken Конечно, вы должны сначала создать экземпляр конвертера в словаре ресурсов, чтобы использовать его. См.правку.

3. «Тип «Больший преобразователь» не был найден. Убедитесь, что вы не пропустили ссылку на сборку и что все сборки, на которые имеются ссылки, были созданы». Мне чего-то не хватает в app.xaml, или я не должен писать это в xaml.cs в представлении, или мне чего-то не хватает в xml с xmln = имя чего-то? я не знаю, что делать

4. Я исправил эту ошибку, но «Тег» GreaterThanConverter » не существует в пространстве имен XML » schemas.microsoft.com/winfx/2006/xaml/presentation «.

5. @Gerken Извините, я забыл указать пространство имен XAML для конвертера. Смотрите обновление. Префикс преобразователя с пространством имен и добавьте объявление пространства имен для пространства имен, в котором находится ваш преобразователь.

Ответ №2:

В вашем случае было бы лучше перенести всю логику выбора цвета в конвертер. Затем вы должны удалить все триггеры и привязать DataGridCell.Background их непосредственно к текущему значению Missing . Вы также можете использовать DataGridTextColumn.CellStyle вместо EditStyle .

 <DataGrid>
  <DataGrid.Resources>
    <IntegerToBrushConverter x:Key="IntegerToBrushConverter" />
  </DataGrid.Resources>

  <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Missing}">
      <DataGridTextColumn.CellStyle>
        <Style TargetType="DataGridCell">
          <Setter Property="Background" 
                  Value="{Binding Missing, Converter={StaticResource IntegerToBrushConverter}}" />
        </Style>
      </DataGridTextColumn.CellStyle>
    </DataGridTextColumn>
  </DataGrid.Columns>
<DataGrid>
 

IntegerToBrushConverter.cs

 class IntegerToBrushConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    switch (value)
    {
      case int numericValue when numericValue == 0: return Brushes.LightGreen; 
      case int numericValue when numericValue > 0: return Brushes.Red; 
      case int numericValue when numericValue > 1 amp;amp; numericValue < 5: return Brushes.Blue; 
      default: return Brushes.Yellow;
    }
  }

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    => throw new NotSupportedException();
}