views:

301

answers:

1

I'm trying to think of a way to make an individual cell within a datagrid glow.

I know that you can apply a dropshadoweffect like this to the whole grid:

 [data:DataGrid.Effect>
  [DropShadowEffect BlurRadius="100" ShadowDepth="0" Color="Red"/>
 [/data:DataGrid.Effect>

but what I really want to do is have the individual cell glow red when the value is >= to 100. It's a bit of a visual niceness to sort the wheat from the chaff of a large grid.

+2  A: 

hi there,

I had a similar requirement not long ago which I solved as follows:

DataGrids can be templated of course, so basically I templated the Columns as follows and then had a Converter that painted the background of my widget according to the data bound to this cell.

<data:DataGridTemplateColumn Header="Overall">
                    <data:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Border Effect="{StaticResource StatusBorderDropShadow}" 
                                Background="{Binding Overall, Converter={StaticResource MiniStatusLightConverter}, Mode=TwoWay}" 
                                Style="{StaticResource StatusBorder}" >                                      
                                <Border.BorderBrush>
                                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                        <GradientStop Color="Black" Offset="0"/>
                                        <GradientStop Color="#FF0D9C3B" Offset="1"/>
                                    </LinearGradientBrush>
                                </Border.BorderBrush>
                            </Border>
                </DataTemplate>
                    </data:DataGridTemplateColumn.CellTemplate>

Have a look at the background binding how it uses the MiniStatusLightConverter.

Here is the converter, in your case you will check if the value is >= 100.

> namespace MyProject.Converters { public class StatusToBrushConverter : IValueConverter { #region Implementation of IValueConverter

private Dictionary<string, List<Color>> colorsMap;

public StatusToBrushConverter()
{
  colorsMap = new Dictionary<string, List<Color>>
                {
                  { "Green", new List<Color> { GetColorFromHexString("#FFC1D7BF"), GetColorFromHexString("#FF21C110"), GetColorFromHexString("#FF074431") } },
                  { "Yellow", new List<Color> { GetColorFromHexString("#FFF2F3EA"), GetColorFromHexString("#FFD7CB10"), GetColorFromHexString("#FFDEFE00") } },
                  { "Red", new List<Color> { GetColorFromHexString("#FFF3EEEA"), GetColorFromHexString("#FFC13C10"), GetColorFromHexString("#FFFE1000") } }
                };
}

public static Color GetColorFromHexString(string s)
{
  s = s.Remove(0, 1);
  var a = System.Convert.ToByte(s.Substring(0, 2), 16);
  var r = System.Convert.ToByte(s.Substring(2, 2), 16);
  var g = System.Convert.ToByte(s.Substring(4, 2), 16);
  var b = System.Convert.ToByte(s.Substring(6, 2), 16);
  return Color.FromArgb(a, r, g, b);
}

public static string GetColourName(object dtoValue)
{
  try
  {
    var str = dtoValue.ToString();
    if (str.Contains("#"))
    {
      return str.Split('#')[1];
    }
    return str;
  }
  catch (IndexOutOfRangeException)
  {
    return string.Empty;
  }
}

public object Convert(object dtoValue, Type targetType, object parameter, CultureInfo culture)
{
  return new RadialGradientBrush
                      {
                        RadiusX = 0.784, 
                        RadiusY = 0.786, 
                        GradientOrigin = new Point(0.88, 0.115),
                        GradientStops = GetGradientStopCollection(GetColourName(dtoValue)), 
                        RelativeTransform = GetTransformGroupForEffect()
                      };
}

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

#endregion

public object GetBasicSolidColorBrush(object dtoValue)
{
  var blueBrush = new SolidColorBrush();

  if (dtoValue == null)
  {
    blueBrush.Color = Colors.White;
    return blueBrush;
  }

  var value = GetColourName(dtoValue);

  if (value == "Green")
  {
    blueBrush.Color = Colors.Green;
  }
  else if (value == "Yellow")
  {
    blueBrush.Color = Colors.Yellow;
  }
  else if (value == "Red")
  {
    blueBrush.Color = Colors.Red;
  }
  else
  {
    blueBrush.Color = Colors.White;
  }

  return blueBrush;
}

private TransformGroup GetTransformGroupForEffect()
{
  var transform = new TransformGroup();
  transform.Children.Add(new ScaleTransform { CenterX = 0.5, CenterY = 0.5 });
  transform.Children.Add(new SkewTransform { AngleX = 0.0, AngleY = 0.0, CenterX = 0.5, CenterY = 0.5 });
  transform.Children.Add(new RotateTransform { Angle = 4.548, CenterX = 0.5, CenterY = 0.5 });
  return transform;
}

private GradientStopCollection GetGradientStopCollection(string colorValue)
{
  var gradientStopCollection = new GradientStopCollection();

  var stop1 = new GradientStop { Offset = 0.0 };
  var stop2 = new GradientStop { Offset = 0.200 };
  var stop3 = new GradientStop { Offset = 0.858 };

  stop1.Color = colorsMap[colorValue][0];
  stop2.Color = colorsMap[colorValue][1];
  stop3.Color = colorsMap[colorValue][2];

  gradientStopCollection.Add(stop1);
  gradientStopCollection.Add(stop2);
  gradientStopCollection.Add(stop3);

  return gradientStopCollection;
}

} }

I hope at least this brings you ideas. Another approach I tried was create an user control and put it on the CellTemplate rather than just the Border but I had issues and users were screaming at me for this functionality. It works and users are happy, that counts too.

I hope it helps

elsharpo