newman
newman

Reputation: 6911

WPF: What's wrong with this DataGridTextColumn style?

I want to create a parameterized style for a DataGridTextColumn using the trick from Thomas Levesque via attached properties. However, I can't make it work for my case.

Basically, I want to convert this

                    <DataGridTextColumn Header="Today Chg $" Binding="{Binding TodaysValueChange, StringFormat=N2}" IsReadOnly="True">
                        <DataGridTextColumn.CellStyle>
                            <Style TargetType="DataGridCell" BasedOn="{StaticResource RightAlignedCellStyle}">
                                <Setter Property="Foreground" Value="{Binding Path=TodaysValueChange, Converter={StaticResource PriceChangeToColor}}"/>
                            </Style>
                        </DataGridTextColumn.CellStyle>
                    </DataGridTextColumn>

into this

                    <DataGridTextColumn Header="Today Chg $" Binding="{Binding TodaysValueChange, StringFormat=N2}" IsReadOnly="True" CellStyle="{StaticResource ColoredCell}" ul:ThemeProperties.SignValue="{Binding TodaysValueChange}" ElementStyle="{StaticResource CellRightAlign}"/>

However, I got this error: “A ‘Binding’ cannot be used within a ‘DataGridTextColumn’ collection. A binding can only be set on a DependencyProperty of DependencyObject.” for binding TodaysValueChange to ul:ThemeProperties.SignValue". I don’t know what it is complaining about.

Here is my ThemeProperties:

public static class ThemeProperties
{
    public static double GetSignValue(DependencyObject obj)
    {
        return (double)obj.GetValue(SignValueProperty);
    }

    public static void SetSignValue(DependencyObject obj, double value)
    {
        obj.SetValue(SignValueProperty, value);
    }

    public static readonly DependencyProperty SignValueProperty = DependencyProperty.RegisterAttached("SignValue", typeof(double), typeof(ThemeProperties), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.Inherits));
}

this is my style resource in App.xaml:

    <Style x:Key="ColoredCell" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
        <Setter Property="Foreground" Value="{Binding Path=ul:ThemeProperties.SignValue, Converter={StaticResource PriceChangeToColor}}"/>
    </Style>

Upvotes: 2

Views: 680

Answers (1)

Thomas Levesque
Thomas Levesque

Reputation: 292725

I can't reproduce your exact problem (I'm not seeing the error you mention), but I can see several problems:

  • DataGrid columns are not part of the visual or logical tree, so they don't inherit the DataContext. Because of this, the binding for the SignValue property has nothing to bind to.
  • Even if the column inherited the DataContext, it still wouldn't work, because the column is "global" to the DataGrid, so it would get the DataGrid's DataContext, not the DataContext for a specific row.
  • When you set the binding in the ColoredCell style, it is relative to the current cell's DataContext, which is a data item and doesn't have the SignValue property set. You would need to make the binding relative to the cell itself (RelativeSource=Self). But because of the other problems above, it wouldn't work either...

Unfortunately I don't think there's an easy way my "parameterized style" trick work in this case, because the thing that needs to change in the style is the binding path, and there is no way to "bind the path of the binding". So I think you should stick to your initial solution (which is not that bad IMO).

Upvotes: 1

Related Questions