Archive for September, 2010

Silverlight VisualState changes using DataBinding not code behind


Download
I hate the fact that I have to keep using code behind to trigger VisualState changes in my view.  Frequently I just want to change a visual state of a control based on the properties of the object to which the control is bound – such as making additional options visible or invisible, changing the mode of the display based on information stored in the model etc.

So I’ve come up with a control that helps!  The VisualStateController can be placed in the XAML for a control and be bound to a property of the databound object using its StateMode dependency property. 

  • If the property is a bool then two further properties OnState and OffState are used to determine the visual state of the control based on the value of the property.
  • If the property is an enum then the visual state will be set the the text string name of the enum value.
  • If the property is a string it will be used to directly set the visual state

Now changes causing normal binding updates will automatically trigger the visual state changes.

<VisualStateCtrls:VisualStateController StateMode="{Binding IsSelected}"
             OnState="Selected"
             OffState="Unselected"/>

<VisualStateCtrls:VisualStateController StateMode="{Binding IsResizable}"
             OnState="Sizers"
             OffState="NoSizers"/>

The VisualStateController binds automatically to the UserControl (or Control) that it is a child of.  You can put it inside any panel within the body of your UserControl’s XAML.

You can find the project and source code here.

If you want to achieve the same thing using triggers and a slightly more wordy approach, you can use blend and triggers – see here for details.

, , , , , , ,

5 Comments

Serializing classes between Silverlight and .NET 4


I’ve realized that I didn’t detail how to ensure you can serialize your own classes between Silverlight and .NET 4 using my SilverlightSerializer class. 

The vital thing to do in these circumstances is to define the classes you want to share in a Silverlight assembly that only references System, System.Core and mscorlib.  These are the requirements for assemblies that can be used in both types of project.  If you define your classes in this way then they can be deserialized on the back end without a problem, reference anything else and it won’t work.  Fortunately most of what you will need is included in those system assemblies!

, ,

1 Comment

Silverlight AllChildren: find all of the visual children of a FrameworkElement


Our application has some occasions where we need to iterate the entire child tree of a visual component. Not a common thing in many applications, I use it to pass visual states to the sub elements of a tree, but if you need a routine for this purpose then I thought I would post mine here:  


        public static List<T> AllChildren<T>(this FrameworkElement ele, Func<DependencyObject, bool> whereFunc = null) where T : class
        {
            if (ele == null)
                return null;
            var output = new List<T>();
            var c = VisualTreeHelper.GetChildrenCount(ele);
            for (var i = 0; i < c; i++)
            {
                var ch = VisualTreeHelper.GetChild(ele, i);
                if (whereFunc != null)
                {
                    if (!whereFunc(ch))
                    {
                        continue;
                    }
                }
                if ((ch is T))
                    output.Add(ch as T);
                if (!(ch is FrameworkElement))
                    continue;

                output.AddRange((ch as FrameworkElement).AllChildren<T>(whereFunc));
            }
            return output;
        }

The function is an extension method that uses the generic Type to decide on the types of children to return.  It takes an optional “Where function” that can be used to stop iterating down branches of the visual tree – please note that the Where function doesn’t only get passed the Type components, it gets everything so you can stop the recursive operation when you want to.  If you don’t pass the Where parameter then all visual children are returned.  

 

                foreach (var c in panel.AllChildren<Control>((child) => !(child is FdTreeViewItem)))
                {
                    VisualStateManager.GoToState(c, "FlowSelected", true);
                } 

   

, , ,

5 Comments