3

I have a style being created in the xaml for my window which contains bindings to a DynamicResource:

<Window.Resources>
    <local:RowColorConverter x:Key="RowColorConverter" />
        <Style x:Key="OddEvenRowStyle">
            <Setter Property="DataGridRow.Background">
                <Setter.Value>
                    <Binding RelativeSource="{RelativeSource AncestorType=GroupItem}" Path="(ItemsControl.AlternationIndex)" Converter="{StaticResource RowColorConverter}">
                        <Binding.ConverterParameter>
                            <x:Array Type="Brush">
                                <SolidColorBrush Color="{DynamicResource RowPrimaryBrush}" />
                                <SolidColorBrush Color="{DynamicResource RowSecondaryBrush}" />
                            </x:Array>
                        </Binding.ConverterParameter>
                    </Binding>
                </Setter.Value>
            </Setter>
        </Style>
</Window.Resources>

I then assign the style to a RowStyle for a DataGrid:

<DataGrid Name="dataGrid" AutoGenerateColumns="False" Height="Auto" Width="Auto" ItemsSource="{Binding}" RowStyle="{StaticResource OddEvenRowStyle}">

In the initialization of my window I'm assigning these DynamicResource values:

Resources["RowPrimaryBrush"] = Colors.LightGray;
Resources["RowSecondaryBrush"] = Colors.DarkGray;

However when I load up the window the colors aren't working correctly:

enter image description here

I'm pretty sure the rest of my code is okay because when I change the Color values in xaml to color values:

<x:Array Type="Brush">
    <SolidColorBrush Color="LightGray" />
    <SolidColorBrush Color="DarkGray" />
</x:Array>

The colors get assigned correctly:

enter image description here

Which is why I'm led to believe it's something to do with the bindings. Is there something wrong with the way I'm binding my colors?

flamebaud
  • 978
  • 1
  • 9
  • 26
  • First thing you need to do is turn up debug messages for databinding: http://i.stack.imgur.com/MF8i5.png Next, re-run and check the output window and see what errors are there. Probably want to turn up trace settings for markup and resource dictionary as well. Also, real nice question. Welcome aboard. –  Jun 25 '12 at 14:46
  • @Will The message I receive for this is `System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.GroupItem', AncestorLevel='1''. BindingExpression:Path=(0); DataItem=null; target element is 'DataGridRow' (Name=''); target property is 'Background' (type 'Brush')` – flamebaud Jun 25 '12 at 15:08
  • I don't think that's the problem, unfortunately. You'll get a lot of false positives like this ("DataItem=null"). BTW, have you tried replacing the dynamic resource with a static one like you did replacing the dynamic resource with an actual color? Just another thing to try. –  Jun 25 '12 at 15:34
  • Just tried changing to Static Resources. Added these: ` ` and changed to this: ` ` still no result – flamebaud Jun 25 '12 at 15:43
  • There's your problem. Resource lookups are failing the way you are using them. –  Jun 25 '12 at 15:46

3 Answers3

3

Binding.ConverterParameter is not part of WPF's logical tree, so performing dynamic resource lookups within it won't work.

Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • 1
    I can understand how that might cause an issue, however do you have a suggestion on resolving my dilemma on passing dynamic brushes to my converter? – flamebaud Jun 25 '12 at 16:12
2

Make sure you set your resources before your window initializes.

public MainWindow()
{
    Resources["RowPrimaryBrush"] = Colors.LightGray;
    Resources["RowSecondaryBrush"] = Colors.DarkGray;
    InitializeComponent();
}

A dynamic resource won't update when changed, like a Binding. Its just deferred until runtime rather than evaluated at compile time.


Not familiar with the limitation, but its not surprising. You might have to rewrite your RowColorConverter to take its argument directly and then update it from codebehind via

(Resources["RowColorConverter"] as RowColorConverter).Parameter = 
    new Brush[]
    {
        Brushes.LightGray, 
        Brushes.DarkGray
    }

Or define an attached property within your RowColorConverter

#region Brushes Attached DependencyProperty
public static readonly DependencyProperty BrushesProperty = DependencyProperty.RegisterAttached(
    BrushesPropertyName,
    typeof(SolidColorBrush[]),
    typeof(RowColorConverter),
    new FrameworkPropertyMetadata(null)
);
public const string BrushesPropertyName = "Brushes";
public static void SetBrushes(DependencyObject element, SolidColorBrush[] value)
{
    element.SetValue(BrushesProperty, value);
}
public static SolidColorBrush[] GetBrushes(DependencyObject element)
{
    return (SolidColorBrush[])element.GetValue(BrushesProperty);
}
#endregion

that you can set differently on each grid

<DataGrid Name="dataGrid" SnipPointlessAttributes="True">
    <local:RowColorConverter.Colors>
        <x:Array Type="Brush">
            <SolidColorBrush Color="LightGray" />
            <SolidColorBrush Color="DarkGray" />
        </x:Array>
    </local:RowColorConverter.Colors>
</DataGrid>
0

Use a MultiBinding instead of a binding with a converter parameter.

Rob van Daal
  • 298
  • 1
  • 9