如何根据条件在DataGrid的单个单元格中制作多色 [英] How to make multicolor in a single cell of DataGrid based on condition

查看:70
本文介绍了如何根据条件在DataGrid的单个单元格中制作多色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,



我需要根据WPF数据网格中的单元格值在单个单元格中进行多色处理。



例如:

我有一个标题为InitialNames的列,另一列标题为Available



假设它包含例如以下内容:

InitialNames

ABC / BD

BVF / GFD / YA

BD



Avaiable

0/1

0/0/0

1



一行中两列的substring.count始终是相同的。



我需要的是基于/对单元格可用进行子串,如果值为1,则InitialNames列中相同索引的颜色将为红色。



我知道如何使用TextBlock.Inlines在代码中执行此操作,但我不知道如何使用new替换datagrid单元格中的结果InitialNames内联彩色字符串。

解决方案

最简单的是使用转换器,我有一个颜色转换器,用于根据对象中的值更改2个单元格的颜色绑定到行。



您将转换器添加到资源然后



 <   Page.Resources  >  
< con:StatusToColorConverter x:键 = StatusToColorConverter / >
< style x:key = RowColorConverted targettype = {x:Type TextBlock} xmlns:x = #unknown >
< setter property = 背景 = {Binding StatusCode,Converter = {StaticResource StatusToColorConverter}} / >
< / style >





然后找到你想要的元素并使用这个风格



 <   DataGridTextColumn    标题  = 职位名称     宽度  =  2 *    绑定  =  {Binding HdrJobTitleName}    ElementStyle   =  {StaticResource RowColorConverted}  /  >  
< DataGridTextColumn 标题 = 状态 宽度 < span class =code-keyword> = 1.75 * 绑定 = {Binding StatusDesc} x:名称 = StatusCol ElementStyle = {StaticResource RowColorConverted} >





这是我的价值转换器代码。



  public   class  StatusToColorConverter:IValueConverter 
{
public object 转换( object value ,输入targetType, object 参数,System.Globalization.CultureInfo文化)
{
SolidColorBrush rtn = null ;
string input = value as string ;
switch (输入)
{
case MMGlobal.NewStatusCode:
rtn = new SolidColorBrush(Colors.LawnGreen);
break ;
case MMGlobal.ErrorStatusCode:
rtn = new SolidColorBrush(Colors.Red) ;
break ;
case MMGlobal.AwaitingStatusCode:
rtn = new SolidColorBrush(Colors.Yellow) ;
break ;
case MMGlobal.CompleteStatusCode:
rtn = new SolidColorBrush(Colors.Gray) ;
break ;
case MMGlobal.ProcessStatusCode:
rtn = new SolidColorBrush(Colors.Lavender) ;
break ;
默认
rtn = new SolidColorBrush(Colors.GhostWhite);
break ;
}

return rtn;
}

public object ConvertBack( object value ,键入targetType, object 参数,System.Globalization。 CultureInfo culture)
{
throw new NotImplementedException();
}
}


感谢您的回复



your b建议将改变单元格的颜色,但我想在单个单元格中使用多色。



下表将使其更容易理解:



如果可用栏如下:



可用

0/1

0/0/0

1

1/0/1

0/0



InitialName列如下:



InitialNames

ABC / BD

BVF / GFD / YA

BM

YVD / LKL / DDS

HGT / FDS



注意:它不是粗体,而是红色,但我不知道如何在我的回复中把它变成红色。


唯一(我能想到的)方法是以不同的颜色(基于两个独立的值)拥有可变数量的文本列是扩展 TextBlock contro l自我构建其内容。这就是我所做的。

 使用 System.Windows; 
使用 System.Windows.Controls;
使用 System.Windows.Documents;
使用 System.Windows.Media;

命名空间 WpfApplication3
{
public class NameAvailableTextBlock:TextBlock
{
public string InitialName
{
get { return )的GetValue(InitialNameProperty); }
set {SetValue(InitialNameProperty, value ); }
}

// 使用DependencyProperty作为Name的后备存储。这样可以实现动画,样式,装订等......
public static readonly DependencyProperty InitialNameProperty =
DependencyProperty.Register( InitialName typeof string ), typeof (NameAvailableTextBlock), new PropertyMetadata( string .Empty,NameAvailableChanged));

public string 可用
{
get { return string )GetValue(AvailableProperty) ; }
set {SetValue(AvailableProperty, value ); }
}

// 使用DependencyProperty作为可用的后备存储。这样可以实现动画,样式,装订等......
public static readonly DependencyProperty AvailableProperty =
DependencyProperty.Register( 可用 typeof string ), typeof (NameAvailableTextBlock), new PropertyMetadata( string .Empty,NameAvailableChanged));

private static void NameAvailableChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
((NameAvailableTextBlock)d).DoNameAvailableChanged();
}

private void DoNameAvailableChanged()
{
Inlines.Clear();
// 检查InitialName或Available == null
string [] names = InitialName.Split(' /');
string [] avail = Available.Split(' / );
if (names.Length!= available.Length)
return ; // 只是挽救,直到我们想看到的数据
for int i = 0 ; i < names.Length; ++ i)
{
if (i > 0
{
Inlines.Add( new 运行( /));
}
var run = new 运行(names [i]);
Inlines.Add(run);
if (avail [i] .Trim()== 1
{
run.Foreground = Brushes.Red;
}
}
}
}
}





< pre lang =xml> < 窗口 x:Class = WpfApplication3.MainWindow

xmlns = http://schemas.microsoft。 com / winfx / 2006 / xaml / presentation

xmlns:x = http://schemas.microsoft.com/winfx/2006/xaml

xmlns:local = clr-namespace:WpfApplication3

< span class =code-attribute> 标题 = MainWindow

高度 = 350

< span class =code-attribute> 宽度 = 525 >
< 网格 > ;
< local:NameAvailableTextBlock 宽度 = 400

高度 = 200

InitialName = {Binding InitialNames}

可用 = {Binding Available} / >
< / Grid >
< / Window >





在MainWindow.xaml.cs中设置DummyDataContext:

 使用 System.Windows; 

命名空间 WpfApplication3
{
/// < 摘要 >
/// MainWindow.xaml $ b的交互逻辑$ b /// < < span class =code-summarycomment> / summary >
public partial class MainWindow:Window
{
public class DummyDataContext
{
public string InitialNames { get { return YVD / LKL / DDS; }
public string 可用{ get { return 1/0/1 ; }
}

public MainWindow()
{
InitializeComponent();
DataContext = new DummyDataContext();
}
}

}



用于 DataGrid ,只需将 local:NameAvailableTextBlock 放入网格列的模板中。

(一个完整的 FlowDocument 可能矫枉过正!)


Hello,

I need to make a multicolor in a single cell based on cell value in WPF datagrid.

For example:
I have a column which header is "InitialNames" and another column with a header "Available"

Let's say that it contains for example the following:
InitialNames
ABC/BD
BVF/GFD/YA
BD

Avaiable
0/1
0/0/0
1

It is all the time the substring.count for both columns in one row are the same.

What I need is that to substring the cell "available" based on "/" and if the value is 1 then the color of the same index in InitialNames column will be red.

I know how to do it in code using TextBlock.Inlines but I don't know how to replace the result in the datagrid cell "InitialNames" with the new inlines colored string.

解决方案

The simplest is to use a converter, I have a color converter that I use to change the colors of 2 cells based on values in the object bound to the row.

You add the converter to the resources and then

<Page.Resources>
        <con:StatusToColorConverter x:Key="StatusToColorConverter"/>
        <style x:key="RowColorConverted" targettype="{x:Type TextBlock}" xmlns:x="#unknown">
            <setter property="Background" value="{Binding StatusCode, Converter={StaticResource StatusToColorConverter}}" />
        </style>



and then find the element you want and use the style

<DataGridTextColumn Header="Job Title Name"  Width="2*" Binding="{Binding HdrJobTitleName}" ElementStyle="{StaticResource RowColorConverted}"/>
<DataGridTextColumn Header="Status" Width="1.75*" Binding="{Binding StatusDesc}" x:Name="StatusCol" ElementStyle="{StaticResource RowColorConverted}">



This is my value converter code.

public class StatusToColorConverter : IValueConverter
 {
     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
     {
         SolidColorBrush rtn = null;
         string input = value as string;
         switch (input)
         {
             case MMGlobal.NewStatusCode:
                 rtn = new SolidColorBrush(Colors.LawnGreen);
                 break;
             case MMGlobal.ErrorStatusCode:
                 rtn = new SolidColorBrush(Colors.Red);
                 break;
             case MMGlobal.AwaitingStatusCode:
                 rtn = new SolidColorBrush(Colors.Yellow);
                 break;
             case MMGlobal.CompleteStatusCode:
                 rtn = new SolidColorBrush(Colors.Gray);
                 break;
             case MMGlobal.ProcessStatusCode:
                 rtn = new SolidColorBrush(Colors.Lavender);
                 break;
             default:
                 rtn = new SolidColorBrush(Colors.GhostWhite);
                 break;
         }

         return rtn;
     }

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


Thank you for your reply

your suggestion will change the color for the cell but I want to use multicolor in single cell.

the following table will make it easier to understand:

If available column as below:

Available
0/1
0/0/0
1
1/0/1
0/0

The InitialName column will be as below:

InitialNames
ABC/BD
BVF/GFD/YA
BM
YVD/LKL/DDS
HGT/FDS

note: instead of bold, it will be red color but I don't know how to make it red in my reply.


The only (that I can think of) way to have a variable number of pieces of a text column in different colors (based on two independent values) is to extend the TextBlock control to self-construct its content. Here's what I've done.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

namespace WpfApplication3
{
  public class NameAvailableTextBlock : TextBlock
  {
    public string InitialName
    {
      get { return (string)GetValue(InitialNameProperty); }
      set { SetValue(InitialNameProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Name.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty InitialNameProperty =
        DependencyProperty.Register("InitialName", typeof(string), typeof(NameAvailableTextBlock), new PropertyMetadata(string.Empty, NameAvailableChanged));

    public string Available
    {
      get { return (string)GetValue(AvailableProperty); }
      set { SetValue(AvailableProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Available.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AvailableProperty =
      DependencyProperty.Register("Available", typeof(string), typeof(NameAvailableTextBlock), new PropertyMetadata(string.Empty, NameAvailableChanged));

    private static void NameAvailableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      ((NameAvailableTextBlock)d).DoNameAvailableChanged();
    }

    private void DoNameAvailableChanged()
    {
      Inlines.Clear();
      // check for either InitialName or Available == null
      string[] names = InitialName.Split('/');
      string[] avail = Available.Split('/');
      if (names.Length != available.Length)
        return;   // just bail-out until the data is what we want to see
      for (int i = 0; i < names.Length; ++i)
      {
        if (i > 0)
        {
          Inlines.Add(new Run("/"));
        }
        var run = new Run(names[i]);
        Inlines.Add(run);
        if (avail[i].Trim() == "1")
        {
          run.Foreground = Brushes.Red;
        }
      }
    }
  }
}


and

<Window x:Class="WpfApplication3.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:local="clr-namespace:WpfApplication3"

        Title="MainWindow"

        Height="350"

        Width="525">
  <Grid>
    <local:NameAvailableTextBlock Width="400"

                                  Height="200" 

                                  InitialName="{Binding InitialNames}"

                                  Available="{Binding Available}" />
  </Grid>
</Window>



With a DummyDataContext set in MainWindow.xaml.cs:

using System.Windows;

namespace WpfApplication3
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {
    public class DummyDataContext
    {
      public string InitialNames { get { return "YVD/LKL/DDS"; } }
      public string Available { get { return "1/0/1"; } }
    }

    public MainWindow()
    {
      InitializeComponent();
      DataContext = new DummyDataContext();
    }
  }

}


For use in a DataGrid, just put the local:NameAvailableTextBlock in the template for the column of the grid.
(A full FlowDocument probably would be overkill!)


这篇关于如何根据条件在DataGrid的单个单元格中制作多色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆