首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据用户输入更改DataGrid前景色?

如何根据用户输入更改DataGrid前景色?
EN

Stack Overflow用户
提问于 2021-10-15 06:56:15
回答 1查看 110关注 0票数 0

我有一个DataGridDataGrid中有12列。这些列中的每一列表示0-255之间的byte值。我想根据用户输入的范围对它们进行着色。

我不知道如何根据用户输入更改这些值。用户可以为每一列指定不同的范围。下面是我手动实现的应用程序。如何将此应用程序绑定到用户登录。

变换器

代码语言:javascript
复制
public class DataGridColorConverter : IValueConverter
{
    public object Convert(
        object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        byte data = (byte)value;

        if (data <= 30)
            return 0;
        else if (data <= 60)
            return 1;
        else if (data <= 90)
            return 2;
        else
            return 3;
    }

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

Xaml

代码语言:javascript
复制
<UserControl.Resources>
    <my:DataGridColorConverter x:Key="DGCConverter"/>
</UserControl.Resources>

<DataGrid Name="MyDataGrid"
          Grid.Row="1"
          AutoGenerateColumns="False" 
          ItemsSource="{Binding JobsCollectionView , IsAsync=True}"
          VirtualizingStackPanel.VirtualizationMode="Recycling"
          IsReadOnly="True"
          Height="480">
    <DataGrid.Columns>
        <DataGridTextColumn Header="ID" Binding="{Binding ID}"/>
        <DataGridTextColumn Header="RTR" Binding="{Binding RTR}"/>
        <DataGridTextColumn Header="IDE" Binding="{Binding IDE}"/>
        <DataGridTextColumn Header="DLC" Binding="{Binding DLC}"/>
        <DataGridTextColumn Header="BYTE-0" Binding="{Binding Byte0}"/>
        <DataGridTextColumn Header="BYTE-1" Binding="{Binding Byte1}"/>
        <DataGridTextColumn Header="BYTE-2" Binding="{Binding Byte2}"/>
        <DataGridTextColumn Header="BYTE-3" Binding="{Binding Byte3}"/>
        <DataGridTextColumn Header="BYTE-4" Binding="{Binding Byte4}"/>
        <DataGridTextColumn Header="BYTE-5" Binding="{Binding Byte5}"/>
        <DataGridTextColumn Header="BYTE-6" Binding="{Binding Byte6}"/>
        <DataGridTextColumn Header="BYTE-7" Binding="{Binding Byte7}">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="{x:Type TextBlock}">

                    <Setter Property="Foreground" Value="Green" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Byte7,Converter={StaticResource DGCConverter}}" Value="1">
                            <Setter Property="Foreground" Value="Yellow" />
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Byte7,Converter={StaticResource DGCConverter}}" Value="2">
                            <Setter Property="Foreground" Value="Orange" />
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Byte7,Converter={StaticResource DGCConverter}}" Value="3">
                            <Setter Property="Foreground" Value="Red" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
        <DataGridTextColumn Header="TIME" Binding="{Binding Time, StringFormat=\{0:dd.MM.yy HH:mm:ss\}}"/>
    </DataGrid.Columns>
</DataGrid>

注意事项:我正在使用MVVM。

备注2:我没有共享用户可以输入值范围的字段,以便它在XAML中不拥挤。

例如,用户希望Blue在0-100之间,Red在100-150之间,Green在150-255之间.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-15 10:56:19

--我不知道如何根据用户输入更改这些值。用户可以为每一列指定不同的范围。

如果用户可以指定范围,例如通过Sliders或TextBoxes,则需要绑定这些值以对更改作出反应。让我们假设这些值映射的画笔不需要绑定(目前)。IValueConverter只能绑定单个值。您可以创建一个IMultiValueConverter,它可以绑定多个值,如其名称所示。具体转换器的外观有多个选项,取决于您的视图、视图模型和其他需求。

下面是一个IMultiValueConverter示例,它允许绑定多个byte属性,其中第一个属性是要比较的原始data值,其余属性表示每个范围的边界。这些范围的Brushes作为parameter (集合)传递,不可绑定。如果您希望它们也是可绑定的,那么它们也将通过values数组传递。此转换器假定所有值都是bytes,而parameterBrushes的集合。此外,必须有不同的范围边界(没有重复的)和相同数量的Brushes (可以是重复的),否则就没有1:1的映射(抛出异常)。如果没有绑定值或可能的映射,则不会返回画笔。

代码语言:javascript
复制
public class DataGridColorConverter : IMultiValueConverter
{
   public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
   {
      if (values == null)
         return Binding.DoNothing;

      var byteValues = values.Cast<byte>().ToList();
      var brushes = ((IEnumerable)parameter).Cast<Brush>().ToList();

      var data = byteValues[0];
      var bounds = byteValues.Skip(1).Distinct().ToList();

      if (bounds.Count != brushes.Count)
         throw new ArgumentException("The number of distinct stops must be equal to the number of stop brushes.");

      foreach (var (boundary, brush) in bounds.Zip(brushes))
      {
         if (data <= boundary)
            return brush;
      }

      return Binding.DoNothing;
   }

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

在XAML中,可以使用新的转换器使用MultiBinding来调整样式。

代码语言:javascript
复制
<Style TargetType="{x:Type TextBlock}">
   <Setter Property="Foreground">
      <Setter.Value>
         <MultiBinding Converter="{StaticResource DataGridColorConverter}">
            <MultiBinding.Bindings>
               <!-- ...binds the current data context, your BYTE 7. -->
               <Binding/>
               <!-- ...these bindings may vary depending on the source for binding, view model, text block, ... -->
               <Binding Path="MyBlueRangeEndProperty"/>
               <Binding Path="MyRedRangeEndProperty"/>
               <Binding Path="MyGreenRangeEndProperty"/>
            </MultiBinding.Bindings>
            <MultiBinding.ConverterParameter>
               <!-- ...this array could also be shared (moved to resource and refernce via {StaticResource ...}). -->
               <x:Array Type="{x:Type Brush}">
                  <SolidColorBrush Color="Blue"/>
                  <SolidColorBrush Color="Red"/>
                  <SolidColorBrush Color="Green"/>
               </x:Array>
            </MultiBinding.ConverterParameter>
         </MultiBinding>
      </Setter.Value>
   </Setter>
</Style>

如上文所述,实现这一目标有许多备选方案。对于您的用例来说,这应该足够了,如果颜色数组对于所有列都是相同的,或者单独定义每个列,那么您甚至可以共享颜色数组。

更新有关使用Zip编译错误的注释。此扩展方法并不适用于所有目标框架。这同样适用于C#语言版本和元组解构。但是,在这些情况下,您可以使用一个简单的for循环。

代码语言:javascript
复制
for (var i = 0; i < bounds.Count; i++)
{
   if (data <= bounds[i])
      return brushes[i];
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69580946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档