none
Binding to a StaticResource...not working. RRS feed

  • Question

  • Hello,

    My datacontext and binding all seem to be working except for my ellipse column.

    <DataGrid.Columns>
         <DataGridTemplateColumn Width="SizeToCells" IsReadOnly="True">
              <DataGridTemplateColumn.CellTemplate>
                   <DataTemplate>
                        <Ellipse Grid.Row="0" Grid.Column="0" Style="{Binding BulletType}" />
                   </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
         </DataGridTemplateColumn>
    ...
    </DataGrid.Columns>

    Nothing shows in the column...at least as far as I can tell. I've tried many different variations for binding the style. I've seen some articles saying you have to create an extension class etc. it was from 2009 so I was hoping you really don't have to do that anymore. FYI I do have the static resources in the datagrid.resources section.

    <DataGrid.Resources>                                          <DropShadowEffect x:Key="BulletsDropShadow" />
       <Style TargetType="Ellipse" x:Key="GoldBullets">
          <Setter Property="Fill" Value="#FFEEB211" />
          <Setter Property="Height" Value="15" />
          <Setter Property="Stroke" Value="#FF1A2674" />
          <Setter Property="Width" Value="15" />
          <Setter Property="Margin" Value="10 10" />
          <Setter Property="Effect" Value="{StaticResource BulletsDropShadow}" />
       </Style>
    ...
    </DataGrid.Resources>

    So what is the trick for getting the Style to grab the proper resource? I am passing the x:Key such as GoldBullet in the viewmodel.

    TIA

    JB

    Thursday, April 19, 2012 9:52 PM

Answers

  • Hi,

     

    you can use Datatriggers if the color types are only 3 or 4 or limited.

     <DataGridTemplateColumn Header="YourColumn">
                        <DataGridTemplateColumn.CellTemplate >
      <DataTemplate>
      <Ellipse Grid.Row="0" Grid.Column="0" Style="{StaticResource GoldBullets}" />
    <DataTemplate.Triggers>
    <DataTrigger Binding="{Binding Bullettype}" Value="GoldBullet">
     <Setter Property="style" Value=""/>                                </DataTrigger>
     <DataTrigger Binding="{Binding Bullettype}" Value="RedBullet">                                        <Setter Property="style" Value=""/>
                                    </DataTrigger>				<DataTrigger Binding="{Binding Bullettype}" Value="GreenBullet">                                        <Setter Property="style" Value=""/>                                </DataTrigger></DataTemplate.Triggers>
      </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>


    Thanks & Regards dhampall

    • Marked as answer by zzpluralza Friday, April 20, 2012 2:49 PM
    Friday, April 20, 2012 10:59 AM
  • Hi,

    So finally you try to bind a string to a Style, which won't work.
    If you deal with StaticResources you have to know that they're
    tied to their property target just once, in he very initial phase
    when the XamlReader does the parsing and so on.

    Later on you can't change them, that's why they're called "static"
    and StaticResources won't help you here.

    In addition to the collegues advice I'd like to add using a
    DynamicResource or an IValueConverter to the recommendation list.
    Where the Converter in the end does more or less the same as a DataTrigger
    i.e. it maps from String to Style(resource) .

    ToDo list:

    1. place the Ellipse style resources into Application.Resources of your App.xaml.
    2. Implement a converter:

    using System;
    using System.Globalization;
    using System.Windows;
    using System.Windows.Data;
    
        public class StringToResourceConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (value == null) return null;
                object result = Application.Current.TryFindResource(value.ToString());
                return result;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return null;
            }
        }
    

    3. Change your DataCellTemplate to sth like:

    <Window
      ...
      xlmns:local="clr-namespace:MyConverts"
    >
    <Window.Resources>
     <local:StringToResourceConverter x:Key="s2rConv" />
    <Window.Resources>
    
    ...
    
    <DataTemplate>
        <Ellipse Grid.Row="0" Grid.Column="0" Style="{Binding Path=BulletType,Converter={StaticResource ResourceKey=s2rConv}}" />
    </DataTemplate>


    Chris

    • Marked as answer by zzpluralza Friday, April 20, 2012 2:56 PM
    Friday, April 20, 2012 1:23 PM
  • You can bind a brush in a style if all you want is a different colour.
    • Marked as answer by zzpluralza Friday, April 20, 2012 2:49 PM
    Friday, April 20, 2012 10:47 AM
    Moderator

All replies

  • Probably you should reference the static style resource directly

    <DataTemplate>
        <Ellipse Grid.Row="0" Grid.Column="0" Style="{StaticResource GoldBullets}" />
    </DataTemplate>
    Passing a style resource to the VM and then back to view through a Binding seems a bit odd to me
    if I understood correctly what you do with the VM and the resource.
    Did you mean that the property "BulletType" returns a string whose value
    equals / is the resource key?


    Chris
    Thursday, April 19, 2012 11:13 PM
  • Well I could do that if I had to. See the bullets are color coded according to category and each category has a datagrid of data points but they all build from one template. I pass the forecolor for the font the same way but because it doesn't reference a staticresource it works just fine. If I had to I could settle for the bullets all being one color.
    Friday, April 20, 2012 1:28 AM
  • OK but what exactely returns the property 'BulletType' of your ViewModel?
    Is it of type string, Style or something else and what exactely is the value?

    Chris
    Friday, April 20, 2012 8:38 AM
  • Sorry for not being clear. It returns type string. Currently the value(s) of "GoldBullet", "RedBullet", "GreenBullet" etc. I've also tried to return the string "StaticeResource GoldBullet". I know it sees the resource as hardcoding the value in XAML works. I didn't think of returning a Style.

    So here are some examples of what I've tried:

    Style="{Binding BulletType}"...BulletType == StaticeResource GoldBullet

    Style="{StaticeResource {Binding BulletType}}".....BulletType == GoldBullet

    I wonder if I could have the ellipse style hardcoded to GenericBullet and have the GenericBullet resource (since it is a local grid resource) bind it fillcolor to a string BulletColor or a solid brush etc?

    I'm going to try that when I get to work this morning.

    JB

    Friday, April 20, 2012 10:37 AM
  • You can bind a brush in a style if all you want is a different colour.
    • Marked as answer by zzpluralza Friday, April 20, 2012 2:49 PM
    Friday, April 20, 2012 10:47 AM
    Moderator
  • Hi,

     

    you can use Datatriggers if the color types are only 3 or 4 or limited.

     <DataGridTemplateColumn Header="YourColumn">
                        <DataGridTemplateColumn.CellTemplate >
      <DataTemplate>
      <Ellipse Grid.Row="0" Grid.Column="0" Style="{StaticResource GoldBullets}" />
    <DataTemplate.Triggers>
    <DataTrigger Binding="{Binding Bullettype}" Value="GoldBullet">
     <Setter Property="style" Value=""/>                                </DataTrigger>
     <DataTrigger Binding="{Binding Bullettype}" Value="RedBullet">                                        <Setter Property="style" Value=""/>
                                    </DataTrigger>				<DataTrigger Binding="{Binding Bullettype}" Value="GreenBullet">                                        <Setter Property="style" Value=""/>                                </DataTrigger></DataTemplate.Triggers>
      </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>


    Thanks & Regards dhampall

    • Marked as answer by zzpluralza Friday, April 20, 2012 2:49 PM
    Friday, April 20, 2012 10:59 AM
  • Hi,

    So finally you try to bind a string to a Style, which won't work.
    If you deal with StaticResources you have to know that they're
    tied to their property target just once, in he very initial phase
    when the XamlReader does the parsing and so on.

    Later on you can't change them, that's why they're called "static"
    and StaticResources won't help you here.

    In addition to the collegues advice I'd like to add using a
    DynamicResource or an IValueConverter to the recommendation list.
    Where the Converter in the end does more or less the same as a DataTrigger
    i.e. it maps from String to Style(resource) .

    ToDo list:

    1. place the Ellipse style resources into Application.Resources of your App.xaml.
    2. Implement a converter:

    using System;
    using System.Globalization;
    using System.Windows;
    using System.Windows.Data;
    
        public class StringToResourceConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (value == null) return null;
                object result = Application.Current.TryFindResource(value.ToString());
                return result;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return null;
            }
        }
    

    3. Change your DataCellTemplate to sth like:

    <Window
      ...
      xlmns:local="clr-namespace:MyConverts"
    >
    <Window.Resources>
     <local:StringToResourceConverter x:Key="s2rConv" />
    <Window.Resources>
    
    ...
    
    <DataTemplate>
        <Ellipse Grid.Row="0" Grid.Column="0" Style="{Binding Path=BulletType,Converter={StaticResource ResourceKey=s2rConv}}" />
    </DataTemplate>


    Chris

    • Marked as answer by zzpluralza Friday, April 20, 2012 2:56 PM
    Friday, April 20, 2012 1:23 PM
  • With a viewmodel I'd personally almost always returning a brush from it and bind rather than use a converter.

    It's the job of the viewmodel to adapt data to the view, so I obviate converters wherever possible.

    Friday, April 20, 2012 1:28 PM
    Moderator
  • Hi Andy,
    Usually I don't recommend converters (because I've read they're considered evil by mvvm autorities ;-)  )
    and prefer Triggers.
    Letting the VM define colors, brushes, fonts and other resources on the other hand is something that seems to couple the VM too tightly to the View too me.
    It think VM kind of hosts the "logical state" of the view but not the detailed styling implementation
    which is what the view does on its own.
    On yet the other hand, returning these things directly is pretty much straight forward.
    So matter of taste and time.

    Chris

    Friday, April 20, 2012 2:20 PM
  • I am trying each of the ways suggested so I can learn more. In the end I went with this way as it was following the KISS principle, and I in my limited knowledge of MVVM (learning every day) understood the VM to adapt data to the view. I do see Mr. Basedau's point about tight coupling (later in the thread) but for this purpose (using the app for a week for a conference) it was acceptable.

    I changed my VM to return a SolidColorBrush and changed my static style:

    <Style TargetType="Ellipse" x:Key="GenericBullets">
         <Setter Property="Fill" Value="{Binding BulletColor}" />

    This works very nicely.

    JB

    Friday, April 20, 2012 2:38 PM
  • This also worked quite nicely and was simple to implement....I mean after I read up and learned what I was doing. As I understand it the trigger matches the binding to the value and if there is a match the setter set's the property. Very cool and this helped me enter a new world of understanding and possibilites. I'm not going to post the code here as it is pretty much identical to what Mr. Hampall (if your not a Mr. my apologies. :)

    In the end this is what I decided. It was relatively true to the KISS principle and loosened the coupling between the VM and View.

    Thank You very much.

    Friday, April 20, 2012 2:49 PM
  • This was the most powerful lesson learned. The complexity of using converters for this application was not the best option as discussed in this thread. HOWEVER since this is an international company while I was learning about converters I saw an immediate application to other projects namely currency and calendar conversion between USD and the Euro, Yen, Rand etc.

    Thank you for your time and patience helping me improve and provide the client with a better product.

    JB

    Friday, April 20, 2012 2:57 PM