As the platform evolves, so do the workarounds [Better SetterValueBindingHelper makes Silverlight Setters better-er!]


This blog has moved to a new location and comments have been disabled.

All old posts, new posts, and comments can be found on The blog of dlaa.me.

See you there!

Comments (27)
  1. Nick says:

    Awesome work, been trying to find a solution to this very issue.

  2. Hello David says:

    I'm not able to get this working with a ListBox, its ListBoxItems and a business object that has an IsSelected property. I want to select my business object at run time and have the ListBoxItem display its selected state. Also, does SL 4 support this type of Setter binding syntax? If not will Silverlight support this in future versions?

  3. David Anson says:

    Hello David,

    This *should* work for the ListBoxItem scenario – be sure you set it up via ItemContainerStyle and use a TwoWay Binding (because both sides need to be able to set the value). If you've tried that and it's not working, let me know and I'll put a sample together.

    Regarding platform support, Silverlight 4 does not support this feature. I'm optimistic it'll show up in a future version of Silverlight, but I can't say for sure.

  4. sandabh says:

    Hi First of all, this is an awesome class. i was just looking for this. I am trying to bind the background color of DataGridRowGroupHeader in SL4

                                       </sdk:DataGrid.RowGroupHeaderStyles>

    i have a Column called as Color coming from the database. i bind data to the datagrid via a WCF webservice like this:

    PagedCollectionView pg = new PagedCollectionView(e.Result);

    pg.GroupDescriptions.Add(new PropertyGroupDescription("AreaHeader"));

    dgAllPacificResults.ItemsSource = pg;

    i put a debugger in the helper class. i see that the value of the column 'Color' never gets hooked up. What could i be doing wrong?

  5. David Anson says:

    sandabh,

    If the type of the thing you're binding to is really Color, that may be the problem – the Background property expects a Brush instance. If that's the case, you could solve this with an IValueConverter that wraps the Color in a SolidColorBrush. Otherwise, I'd recommend simplifying things as much as possible – possibly in a separate project – so you can narrow down exactly what aspect of the scenario is getting in the way here.

    Hope this helps!

  6. sandabh says:

    Thanks David. my xaml did not get posted completely on my previous post. i tried to use a IValueConverter like this:

                                           <Style TargetType="sdk:DataGridRowGroupHeader">

                                               <Setter Property="local:SetterValueBindingHelper.PropertyBinding">

                                                   <Setter.Value>

                                                       <local:SetterValueBindingHelper>

                                                           <local:SetterValueBindingHelper Property="Background" Binding="{Binding GroupBackgroundColor,Converter={StaticResource StringToBrushConverter},ConverterParameter=d}"></local:SetterValueBindingHelper>

                                                       </local:SetterValueBindingHelper>

                                                   </Setter.Value>

                                               </Setter>

    GroupBackgroundColor here is the value i get from my wcf web service which gets it from the database. But unfortunately it still does not  set the background for the row group header. Will this binding from wcf data work the same way as shown for item class in your sample?

    Thanks

  7. David Anson says:

    sandabh,

    Assuming the types are correct and things are hooked up right, I'm not aware of anything special about the results of a WCF call that should get in the way here. As I was saying, you might try simplifying things, Binding to alternate properties as an experiment, and even setting breakpoints in the SetterValueBindingHelper code to see if it's getting invoked at all. One other thing is to check the Output window in Visual Studio when running in debug mode because sometimes there's helpful information hiding there. 🙂

  8. sandabh says:

    You were right David. That worked great!! 🙂 i was not supposed to set GroupBackgroundColor in the Binding. i used the CollectionViewGroup in the converter to fetch the string color from the datasource and then rerurn back the SolidColorBrush. Thanks for all the help. This is an awesome Binding Helper class.

  9. peter says:

    This is good!! Is there a catch? I have been struggling to implement a master-detail view with a treeview using the MVVM pattern. But the SelectedItem property of TreeView is readonly and could not find any way to bind the IsSelected property of TreeViewItem. Until now, thank you. Where can I vote to get this feature included in future versions of Silverlight?

  10. David Anson says:

    peter,

    Great – I'm glad I could help! You can probably find an existing work item to vote on here: silverlight.codeplex.com If not, feel free to open a new one. 🙂

    Thanks for your note!

  11. Nick J says:

    Thank you for this Delay, I've been trying to find a work around for the TreeView SelectedItem (with MVVM) for while now and this works great!! Thanks again!

  12. David Anson says:

    Nick J,

    Yep, the TreeView scenario is one of the best examples of how much easier an MVVM-like approach can make things sometimes. 🙂

  13. Shmulik R. says:

    again.. Good Work!

  14. Scott Anderson says:

    My god thank you.  I used this to toggle the background color on DataGrid rows based on data bindings and it works like a champ.

    Excellent!

  15. Gilles Radrizzi says:

    This saved me a lot of headache. Thanks for the great work

  16. Bruce Denham says:

    Hey David,

    I'm trying (unsuccessfully) to bind set a binding on the IsEnabled Property of a ListBoxItem in my ItemContainerStyle XAML using the ElementName and Path binding properties as shown here:

           <Setter Property="helper:SetterValueBindingHelper.PropertyBinding">

               <Setter.Value>

                   <helper:SetterValueBindingHelper>

                       <helper:SetterValueBindingHelper

                       Type="System.Windows.Controls.ListBoxItem"

                       Property="IsEnabled"

                       Binding="{Binding ElementName=itemText, Path=IsEnabled, Mode=TwoWay}"/>

                   </helper:SetterValueBindingHelper>

               </Setter.Value>

           </Setter>

    Does SetterValueBindingHelper support this? Or am I asking too much of it? I'll probably take a different route for the binding, but I was just curious.

    Thanks,

    Bruce

  17. David Anson says:

    Bruce Denham,

    I think you're asking to much with your use of ElementName – I'm not sure I've ever seen it used like that. 🙂 The good news is that you shouldn't need ElementName here – if you switch to a normal Binding to your model object, you can expose the same bool information there and that'll save you the complexity of fetching it from some other UI element via ElementName.

    Hope this helps!

  18. Scott St.Cyr says:

    David, great posting.  However, I can't get it to work on a ListBoxItem style to create a Canvas ListBox.  Here is my sample code (this is not complete, but complete enough for demo)…

    <UserControl.Resources>

       </UserControl.Resources>

       <ListBox x:Name="LayoutRoot" Background="LightYellow"

           ItemContainerStyle="{StaticResource CanvasListBoxItemStyle}">

           <ListBox.ItemsPanel>

               <ItemsPanelTemplate>

                   <Canvas />

               </ItemsPanelTemplate>

           </ListBox.ItemsPanel>

           <ListBox.ItemTemplate>

               <DataTemplate>

                   <Rectangle   Width="30" Height="30" />

               </DataTemplate>

           </ListBox.ItemTemplate>

       </ListBox>

    </UserControl>

    Unfortunately, the code fails to find the Canvas.Left dependency property

               // Get the DependencyProperty for which to set the Binding

               DependencyProperty property = null;

               var field = type.GetField(

                   item.Property + "Property",

                   BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static);

    Any input greatly welcome.  

  19. Scott St.Cyr says:

    It looks like the top part of my post was cut off, but I discovered the problem.  I was using the

                           <local:SetterValueBindingHelper Property="Canvas.Left" Binding="{Binding X}" />

    instead of

                           <local:SetterValueBindingHelper Type="Canvas" Property="Left" Binding="{Binding X}" />

    It now works fine.  Thanks for the great tool!

  20. David Anson says:

    Scott St.Cyr,

    Cool – glad I could help! 🙂

  21. David Hollema says:

    Hi David…I'm trying to apply this to the ItemContainerStyle of a ListBox as follows.

                                           <ListBox.ItemContainerStyle>

                                           </ListBox.ItemContainerStyle>

    Initially when I run the application and data bind the items source of this listbox (in MVVM style), the above property binding doesn't appear to have any affect.  However, as soon as I scroll down in the listbox, then suddenly the IsEnabled property properly gets applied from item to item.  It takes me scrolling down and back up to "apply" this property.  Any ideas what's going on?

  22. David Anson says:

    David Hollema,

    Offhand (and without any code to go on), it sounds like what you're doing should work correctly. It's possible you're hitting some timing issue, so you might see if changing the order things happen in makes any difference. You don't say how much you need to scroll to get this working, but if it's a significant amount (i.e., a couple of screens), then you might be running into something to do with container virtualization. If so, then switching the ListBox's ItemsPanel to a StackPanel might help (though you'd lose virtualization). But at least that would help identify the source of the problem…

  23. Apurva Sharma says:

    Hi David,

    Thanks for the Helper class. I am trying to make it work for a TreevIew, wherein I wanted the selected treeviewItem to be automatically expanded, so I tried using your helper class to bind the IsExpanded property to the IsSelected property, but then it is essentially tring to find the IsSelected on the ViewModel, so I tried adding two instances of the helper class, one to get the IsSelected to push the state to the VM, and another to get the boolean property from the ViewMode. But that also does not work.

    Could you please help?

    Thanks.

  24. David Anson says:

    Apurva Sharma,

    I'm not sure I understand the problem you're having, but the good news is that others have written about this topic as well. In particular, I consider the following article by Josh Smith to be required reading for anyone dealing with TreeViews in WPF because he covers the relevant issues so well: http://www.codeproject.com/…/TreeViewWithViewModel.aspx

    Happy reading! 🙂

  25. Waleed says:

    Dear David,

    Is it possible to use values from resource files (.resx) in the binding to styles using your workarround.

    Somthing like:

    <Setter Property="helper:SetterValueBindingHelper.PropertyBinding">

              <Setter.Value>

                  <helper:SetterValueBindingHelper>

                      <helper:SetterValueBindingHelper

                      Type="System.Windows.Controls.HyperLink"

                      Property="FontFamily"

                      Binding="{Binding Source=ResourceWrapper, Path=AppStrings.FontName, Mode=TwoWay}"/>

                  </helper:SetterValueBindingHelper>

              </Setter.Value>

          </Setter>

    Best regards

  26. David Anson says:

    Waleed,

    Assuming that Binding would work if applied directly to an element, I'd expect it to work here as well.

    Hope that helps!

  27. Eugene Golushkov says:

    I adapted this solution for WinRT/C++ where reflection is not available. Sources and usage sample is here eugene-gff.livejournal.com/2070.html

Comments are closed.