6
votes

I try to built a DataGrid, and I want to bind one of the TextColums' Foreground property to a Date, so that it becomes red, if the Date is in the past.

Here the XAML:

<toolkit:DataGridTextColumn 
   Binding="{Binding Path=Prüfdatum, Converter={StaticResource TimestampToDateConverter}}"
   Header="Prüfdatum" 
   Foreground="{Binding Path=Prüfdatum, Converter={StaticResource TimestampToColorConverter},
   ConverterParameter=Prüfdatum}" />

Here my Converter:

    class TimestampToColorConverter: IValueConverter
{
    #region IValueConverter Member

    public object Convert(object value, Type targetType, 
           object parameter, System.Globalization.CultureInfo culture)
    {
        string Datum = value.ToString();
        int year = System.Convert.ToInt32(Datum.Substring(6, 4));
        int month = System.Convert.ToInt32(Datum.Substring(3, 2));
        int day = System.Convert.ToInt32(Datum.Substring(0, 2));
        int hour = System.Convert.ToInt32(Datum.Substring(11, 2));
        int minute = System.Convert.ToInt32(Datum.Substring(14, 2));
        int second = System.Convert.ToInt32(Datum.Substring(17, 2));
        DateTime Time = new DateTime(year, month, day, hour, minute, second);
        if (Time < System.DateTime.Now)
        {
            return Brushes.Red as Brush;
        }
        else
        {
            return Brushes.Black as Brush;
        }

    }

    public object ConvertBack(object value, Type targetType, 
         object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }

    #endregion
}

I don't know what is wrong, but the Converter is not even caled (The first Converter works perfectly). The output window shows this:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Prüfdatum; DataItem=null; target element is
'DataGridTextColumn' (HashCode=16187528); target property is 'Foreground' (type 'Brush')

I hope you can help me, guys

Thx

3

3 Answers

0
votes

Since you have binded to DataGrid so no need of "Binding" in DataGridTextColumn and ConverterParameter also not needed because your converter is not using the parameter. Try below

<toolkit:DataGridTextColumn  Header="Prüfdatum" Foreground="{Binding Path=Prüfdatum, Converter={StaticResource TimestampToColorConverter}}" />
8
votes

DataGridTextColumn tells the DataGrid to create a TextBlock for every row in that column. DataGridTextColumn.Binding then setups a binding for TextBlock.Text, which gets fired each time a new row and a new TextBlock for that row gets created.

I don't know if the binding ever gets executed, but at most once (i.e. not for every row):

Binding="{Binding Path=Prüfdatum, Converter={StaticResource TimestampToDateConverter}}"

The correct solution is to create a style for that textblock and to define a binding for ForeGround. This will get executed for every TextBlock generated. The challenge here is for the TextBlock to find the data. This can be achieved with a relative binding to DataGridRow, an ancestor in the visual tree. DataGridRow.Item gives access to the data behind the grid:

<Window.Resources>
  <Style x:Key="ForegroundStyle" TargetType="TextBlock">
    <Setter Property="Foreground" 
      Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}, 
      Path=Item.Prüfdatum, 
      Converter={StaticResource TimestampToColorConverter}/>
  </Style>
</Window.Resources>

<DataGrid>
  <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding SomeData}" ElementStyle="{StaticResource ForegroundStyle}"/>
</DataGrid.Columns>

Complicated right ? I recommend you to read my detailed article about datagrid formatting at: http://www.codeproject.com/Articles/683429/Guide-to-WPF-DataGrid-formatting-using-bindings?msg=5037235#xx5037235xx

Good luck, you need it :-)

1
votes

The DataGridTextColumn Foreground property data binding does not work.

Peter Huber's answer is a good solution. Here is a slightly simpler alternative.

<DataGridTemplateColumn Header="Heading">
    <DataGridTemplateColumn.CellTemplate >
        <DataTemplate>
            <TextBlock Text="{Binding SomeData}" 
                Foreground="{Binding SomeData, Converter={StaticResource TimestampToColorConverter}}" />
       </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>