3

DataGrid.ItemSource gets set in code behind to a dataview. Column names and count needs to change on the fly, so a list of objects doesn't work very well.

I have the table display working completely correctly. Which is great, but my GridCellStyle passes the DataRowView to the converter, instead of the DataGridCell which is what I expected to pass.

Is there a way to either get the DataGridCell content OR something indicating which column is current passed to my converter?

<UserControl x:Class="TestUI.SilveusTable"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:TestUI"
             mc:Ignorable="d" 
             >
    <UserControl.Resources>
        <local:CbotValueConverter x:Key="CbotValueConverter" />
        <Style x:Key="GridCellStyle" TargetType="{x:Type DataGridCell}">
            <Setter Property="Background" Value="Yellow"/>
            <Setter Property="Foreground" Value="{Binding Converter={StaticResource CbotValueConverter}}"/>
        </Style>
    </UserControl.Resources>
    <Grid>
        <DataGrid x:Name="DataGrid1" IsReadOnly="True" CellStyle="{StaticResource GridCellStyle}" />
    </Grid>
</UserControl>

Here is my Converter Class

  [ValueConversion(typeof(DataGridCell), typeof(SolidColorBrush))]
    public class CbotValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var dgc = (DataGridCell) value;
            var rowView = (DataRowView) dgc.DataContext;
            var v = rowView.Row.ItemArray[dgc.Column.DisplayIndex];

            decimal amount;
            if (decimal.TryParse(v.ToString(), out amount))
            {
                if (amount >= 10) return Brushes.Red;
                if (amount >= 5) return Brushes.Blue;
                if (amount > 0) return Brushes.Green;
            }

            return Brushes.Black; //quantity should not be below 0
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
Richard June
  • 706
  • 5
  • 15
  • "which is what I expected to pass." That's a wrong expectation. Unless you explicitly set a binding source (by Source, RelativeSource or ElementName) a Binding uses the current DataContext as its source. Here it is the current element from the Items or ItemsSource collection. – Clemens Nov 29 '16 at 14:57
  • Given that the style is bound to a *DataGridCell*, and the tag is *CellStyle*, expecting it would pass the very thing it's bound to into the converter seems like a very reasonable expectation. How else are you going to perform a conversion based on the contents of a Cell? – Richard June Nov 29 '16 at 15:24
  • A Style isn't bound to anything. Properties in Style Setters can be bound to properties of the current DataContext, unless the Binding explicitly specifies a different source. Besides that, the content of a cell isn't a DataGridCell. See here: [Data Templating Overview](https://msdn.microsoft.com/en-us/library/ms742521(v=vs.110).aspx). – Clemens Nov 29 '16 at 16:54
  • 1
    @RichardJune, try RelativeSource Self to bind a cell `{Binding Converter={StaticResource CbotValueConverter}, RelativeSource={RelativeSource Self}}` – ASh Nov 29 '16 at 17:41
  • @ASh That answered my question. if you put your comment in an answer, I'll mark it complete. – Richard June Nov 29 '16 at 19:56

1 Answers1

4

change the Source of a binding

with currect binding declaration, DataContext of DataGridCell is the Source

Value="{Binding Converter={StaticResource CbotValueConverter}}"

to use DataGridCell itself add RelativeSource Self part (refers to the element on which you are setting the binding)

Value="{Binding Converter={StaticResource CbotValueConverter}, 
                RelativeSource={RelativeSource Self}}"
ASh
  • 34,632
  • 9
  • 60
  • 82