Tag: SilverLight

  • Data-binding Radio Buttons in Silverlight to Enum

    In Silverlight there is no Enum.Getvalue() method, so there is not out-of-the box way of databinding a radio buttongroup to an enumerable value in a viewmodel.

    Step forward converters.

    using System;
    using System.Windows.Data;
    namespace YourNamespace
    { public class EnumBoolConverter : IValueConverter
    { #region Methods
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    { if (value == null || parameter == null)
    return value;
    return value.ToString() == parameter.ToString();
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
    if (value == null || parameter == null)
    return value;
    return Enum.Parse(targetType, (String)parameter, true);
    }
    #endregion Methods
    }
    }

    With the previous convertor it is then quite simple to bind the radio button list. Simply pass the Enum value (as a string) as the converter parameter, and you are away:

    <UserControl
    ...>

    <YourNamespace:EnumBoolConverter
    x:Key="ConvertEnum" />


    <RadioButton
    Content="Yes"
    GroupName="Group1"
    IsChecked="{Binding Path=UserOption, Mode=TwoWay, Converter={StaticResource ConvertEnum}, ConverterParameter=Yes}" />
    <RadioButton
    Content="No"
    GroupName="Group2"
    IsChecked="{Binding Path=UserOption, Mode=TwoWay, Converter={StaticResource ConvertEnum}, ConverterParameter=No}" />
    <RadioButton
    Content="Both"
    GroupName="Group3"
    IsChecked="{Binding Path=UserOption, Mode=TwoWay, Converter={StaticResource ConvertEnum}, ConverterParameter=Both}" />



    Also make sure the GroupName on each radio button is different or the system gets monumentally confused and throws a StackOverflowException.

  • Walking the XAML VisualTree to find a parent of type

    To find a parent item of type T, you can use the following helper class:

    public static class DependencyObjectHelper
    {
    public static DependencyObject FindParent(this DependencyObject obj, Predicate where) {
    var parent = VisualTreeHelper.GetParent(obj);
    
    if (parent == null || where(parent)) {
    return parent;
    } else {
    return parent.FindParent(where);
    }
    }
    
    public static T FindParentOfType(this DependencyObject obj) where T : DependencyObject {
    return (T)FindParent(obj, x => x is T);
    }
    }

    This can then be utilised as follows:

    Grid item = ((DependencyObject)childObject).FindParentOfType();

    This was particularly useful when wanting to locate an invalid control from a ValidationSummary in silverlight, that was nested in an accordian panel:

    BIG shout out goes to Jedi Master Twist for the lead on this 🙂

  • Silverlight PRISM Commands – TextChanged

    Out of the box the Patterns and Practices PRISM code only supports the click event handler. Writing additional handlers really is very easy. Firstly there are two great starter blogs which I’m not going to recreate:

    How Commanding Works in Prism and MVVM by Erik Mork and A code snippet to quickly write Prism commands by Andrea Boschin

    Following these patterns it was a sinch to create the code that can be used as a TextChanged command handler:

      1:     public class TextChangedCommandBehavior : CommandBehaviorBase
      2:     {
      3:         public TextChangedCommandBehavior(TextBox targetObject)
      4:             : base(targetObject)
      5:         {
      6:             targetObject.TextChanged += (s, e) => base.ExecuteCommand();
      7:         }
      8:     }
      9: 
     10:     public static class TextChanged
     11:     {
     12:         public static readonly DependencyProperty TextChangedBehaviorProperty =
     13:             DependencyProperty.RegisterAttached(
     14:                 "TextChangedBehavior", typeof(TextChangedCommandBehavior),
     15:                 typeof(TextChangedCommandBehavior), null);
     16: 
     17:         #region CommandProperty
     18: 
     19:         public static readonly DependencyProperty CommandProperty =
     20:             DependencyProperty.RegisterAttached(
     21:                 "Command", typeof(ICommand), typeof(TextChanged),
     22:                 new PropertyMetadata(CommandProperty_Changed));
     23: 
     24:         public static ICommand GetCommand(DependencyObject obj)
     25:         {
     26:             return (ICommand)obj.GetValue(CommandProperty);
     27:         }
     28: 
     29:         public static void SetCommand(DependencyObject obj, ICommand value)
     30:         {
     31:             obj.SetValue(CommandProperty, value);
     32:         }
     33: 
     34:         private static void CommandProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
     35:         {
     36:             TextBox targetObject = dependencyObject as TextBox;
     37: 
     38:             if (targetObject != null)
     39:                 GetOrCreateBehavior(targetObject).Command = e.NewValue as ICommand;
     40:         }
     41: 
     42:         #endregion
     43: 
     44:         #region CommandParameterProperty
     45: 
     46:         public static readonly DependencyProperty CommandParameterProperty =
     47:             DependencyProperty.RegisterAttached(
     48:                 "CommandParameter", typeof(object),
     49:                 typeof(TextChanged), new PropertyMetadata(CommandParameterProperty_Changed));
     50: 
     51:         public static ICommand GetCommandParameter(DependencyObject obj)
     52:         {
     53:             return (ICommand)obj.GetValue(CommandParameterProperty);
     54:         }
     55: 
     56:         public static void SetCommandParameter(DependencyObject obj, ICommand value)
     57:         {
     58:             obj.SetValue(CommandParameterProperty, value);
     59:         }
     60: 
     61:         private static void CommandParameterProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
     62:         {
     63:             TextBox targetObject = dependencyObject as TextBox;
     64: 
     65:             if (targetObject != null)
     66:                 GetOrCreateBehavior(targetObject).CommandParameter = e.NewValue;
     67:         }
     68: 
     69:         #endregion
     70: 
     71:         private static TextChangedCommandBehavior GetOrCreateBehavior(TextBox targetObject)
     72:         {
     73:             TextChangedCommandBehavior behavior = targetObject.GetValue(TextChangedBehaviorProperty) as TextChangedCommandBehavior;
     74: 
     75:             if (behavior == null)
     76:             {
     77:                 behavior = new TextChangedCommandBehavior(targetObject);
     78:                 targetObject.SetValue(TextChangedBehaviorProperty, behavior);
     79:             }
     80: 
     81:             return behavior;
     82:         }
     83:     }

  • Silverlight 2: Nested user controls, data-binding and property change notification.

    The Problem:

    The parent form is in charge. This form has a view-model which has all the relevant information loaded, know which other views have been implemented, what data those view need and how and when to display and update those views. This is the master page.

    Within that page you can add user controls. These controls are discreet and reusable. They know about themselves, and any controls nested within. The values within these controls are bound to properties in a backing store (the view-model). This control does not know about it’s parent, it will just generate a notification event when the property changes. The parent must be enabled to process this event.

    A Solution:

    Start with your child control. These should function irrespective of where they are called from. For example a reusable data-grid control. In our situation, this control not only displays a collection of objects, it also dynamically sets the displayed fields in the data-grid, based on a collection of field definitions. This control has a view-model (to which the UI controls are data-bound). It also has dependency properties (which can be set by a parent class) and notification properties (which can notify the parent class of changed properties).So the ViewModel would be coded as follows:

      1:     /// 
      2:     /// Backing class for the data used within the UserControl_View
      3:     /// 
      4:     public class UserControl_ViewModel : ViewModelBase
      5:     {
      6: 
      7:         private ObservableCollection<object> _objectList;
      8:         public ObservableCollection<object> ObjectList
      9:         {
     10:             get { return _objectList;}
     11:             set
     12:             {
     13:                 _objectList = value;
     14:                 _OnPropertyChanged("ObjectList");
     15:             }
     16:         }
     17: 
     18:         private object _selectedObject;
     19:         public object SelectedObject
     20:         {
     21:             get { return _selectedObject;}
     22:             set
     23:             {
     24:                 _selectedObject;= value;
     25:                 _OnPropertyChanged("SelectedObject");
     26:             }
     27:         }
     28: 
     29:     }

    (where the ViewModelBase class takes care of the notification property interface).

    Within the UserControl_View we implement the INotifyPropertyChanged interface again, add an instance of the ViewModel class, and bind to it (We also set an event handler into the View to process the properties being changed in the ViewModel and pass these back into the respective UI dependency properties):

      1:     public partial class UserControl_View : UserControl, INotifyPropertyChanged
      2:     {
      3:         public UserControl_ViewModel ViewModel = new UserControl_ViewModel();
      4: 
      5:         public UserControl_View()
      6:         {
      7:             InitializeComponent();
      8:             this.DataContext = ViewModel;
      9: 
     10:             ViewModel.PropertyChanged += new PropertyChangedEventHandler(ViewModel_PropertyChanged);
     11:         }
     12: 
     13: 
     14:         public event PropertyChangedEventHandler PropertyChanged;
     15:         protected virtual void OnPropertyChanged(string propertyName)
     16:         {
     17:             PropertyChangedEventHandler pceh = PropertyChanged;
     18:             if (pceh != null)
     19:             {
     20:                 pceh(this, new PropertyChangedEventArgs(propertyName));
     21:             }
     22:         }
     23:     
     24:         ...
     25:     }

    The event handler for the ViewModel property changed event is as follows:

      1:         /// Watch for the property changed events in teh view model, and get the values
      2:         void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
      3:         {
      4:             if (e!=null)
      5:             {
      6:                 if (e.PropertyName == "SelectedObject")
      7:                 {
      8:                     SelectedObject = ((UserControl_ViewModel)sender).SelectedObject ;
      9:                     OnPropertyChanged("SelectedObject");
     10:                 }
     11:             }
     12:         }

    This will respond to property notification from the ViewModel, check the name of the property, set the respective dependency property on the VIew, and then raise a property notification event for the View (back to the parent).

    We then add dependency properties to the View to handle the objects being passed into the View, for example:

      1:         public ObservableCollection<object> ObjectCollection
      2:         {
      3:             get { return (ObservableCollection<object>)GetValue(ObjectCollectionProperty); }
      4:             set { SetValue(ObjectCollectionProperty, value); }
      5:         }
      6: 
      7:         /// 
      8:         /// Registration of a property container to hold the collection of objects.
      9:         /// 
     10:         /// This HAS to be a dependency property for parent controls to access this.
     11:         public static readonly DependencyProperty ObjectCollectionProperty =
     12:             DependencyProperty.Register("ObjectCollection",
     13:             typeof(ObservableCollection<object>),
     14:             typeof(UserControl_View),
     15:             new PropertyMetadata(new PropertyChangedCallback(ObjectCollectionChanged)));
     16: 
     17:         /// this method is called from the static DependencyProperty "ObjectCollectionProperty"
     18:         /// by the 4th argument as the PropertyMetadata callback value.
     19:         /// This sets the items in the datagrid
     20:         public static void ObjectCollectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
     21:         {
     22:             CaseDataGrid instance = d as CaseDataGrid;
     23:             if (instance != null)
     24:             {
     25:                 if (args.NewValue != null)
     26:                 {
     27:                     instance.ViewModel.ObjectCollection = args.NewValue as ObservableCollection<object> ;
     28:                 }
     29:             }
     30:         }

    Once all the DP’s for the View have been added you are complete with the control. Next you will look at the middle layer.

    Conceptually the middle layer works in exactly the same way as the child layer.

    • A ViewModel is used to maintain and bind data.
    • Notification properties are used from the ViewModel to the View
    • Notification properties are used from the View to any parents.
    • Dependency properties are registered in the view, to accept incoming data from a parent .
    • PropertyChangedCallback methods are used to set the properties on the child controls:

        1:         public static void ObjectCollectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
        2:         {
        3:             ChildControl instance = (ChildControl)d;
        4:             if (instance != null)
        5:             {
        6:                 if (args.NewValue != null)
        7:                 {
        8:                     ObservableCollection<object> NewCollection = args.NewValue as ObservableCollection<object>;
        9:                     instance.UserControl_View.ObjectCollection = NewCollection;
       10:                 }
       11:             }
       12:         }

    The Master Control

    Once again the conceptual model is very  similar to the middle layer:

    • A view model is used to manage and bind data.
    • Notification properties are used to pass data from the ViewModel to the View.
    • The Master_View XAML binds the ViewModel properties to the Child Dependency Properties.

    This should work a treat 🙂

  • Silverlight 3, Validation, MVVM, WCF and EF

    All the current articles and tutorials on Silverlight 3 Validation show really simplistic examples, business objects in the UI space, no services etc etc

    My Problem

    When the business objects are being created and managed via the entity framework, there does not appear to be any simple ways of adding the validation properties to the object fields. This means that by the time the object gets to the UI, we have no control.

    in addition to this I need to be able to provide UI base validation and messaging based on user inputs. This has to happen on the field edit and also on “Save click”. Not as easy as it sounds.

    MY Workaround

    Anyway, I have a workaround that appears to be doing what I need. This involves a few more tweaks than I feel is appropriate, so I’d be interested to hear your thoughts on this approach. Anyway, our form is as follows:

    Previously we had a business object in the ViewModel (FocusedDepartment) and were binding the values of the textboxes to the fields of this object, for example:

    <TextBox x:Name="Txt_Number" Text="{Binding Mode=TwoWay, Path=FocusedDepartment.DepartmentId}" />

    The problem with this was the FocusedDepartment type (Department) was derived from the service layer, which in turn had come from our EF model. We did not find a solution to attach the validation properties to the EF model objects. The workaround for this was to add specific properties into the ViewModel to support the fields, and attach validation properties to these:

    This property still uses the FocusedDepartment property as a backing store. In the xaml we changed our binding to use this new property:

    <TextBox x:Name="Txt_Number" Text="{Binding Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True, Path=DepartmentId}" />

    The FocusedDepartment property also had to notify property changes for the new fields:

    //the currently selected item, bound to the datacontext of the view
    private Department _focusedDepartment = new Department();
    public Department FocusedDepartment
    {
    get { return _focusedDepartment; }
    set
    {
    _focusedDepartment = value;
    _OnPropertyChanged("FocusedDepartment");


    _OnPropertyChanged("Description");
    _OnPropertyChanged("DepartmentId");
    }
    }

    From this point we where able to see the validation on the text boxes appear correctly but only when the values in the textboxes had been changed.

    When tabbing through the fields, the bound fields where not getting touched, so the validation was not occurring. To workaround this issue I have added some code to the Save button click event (sorry MVVM purists!!) to update the source of the binding expressions, then checked the error count against the ViewModel before submitting the save action:

    Firstly, I have a handler to manage the error count in the VM

    Then handled the save button click in code behind

    This ensures the fields are valid (and the validation messages are displayed) before committing the Save action to the service.

    This approach (particularly the checking and setting of values directly in the VM) feels pretty dirty at the moment L, but it does seem to work for UI validation.

  • Silverlight MVVM and Testing

    During my investigations into this crazy land I have found a few good articles (and many not so good…):

    http://www.cauldwell.net/patrick/blog/MVVMAndTestingSilverlight.aspx

    http://silverlight.net/blogs/justinangel/archive/2009/02/25/silverlight-unit-testing-rhinomocks-unity-and-resharper.aspx

    Both use MVVM and both use RhinoMocks, but in subtly different ways.

  • Silverlight unit testing requirements

    When setting up a Silverlight Unit Testing class the following using statements and inheritance must be applied:

    These are required for the TestPanel and EnqueueX methods (particularly inheritance).

    For more on the Inner Class Pattern, take a look at the Type Mock training blog.

  • Asynchronous Lambda Method calls

    You won’t get any benefit using this code, but it makes for more manageable source. So from Pete Browns blog:

    All network calls in Silverlight are asynchronous. The proliferation of event handling functions this can cause just makes for really cluttered code. Using lambda expressions seems to make my code a bit cleaner. (You can also use regular anonymous delegates, but the lambdas involve less typing)

    public void LoadPolicyDetail()
    {
    IvcDataServiceClient client = new IvcDataServiceClient();

    client.GetPolicyDetailCompleted += (s, e) =>
    {
    if (e.Result != null)
    {
    _policyDetail = e.Result;

    if (PolicyDetailLoaded != null)
    PolicyDetailLoaded(this, new EventArgs());
    }
    else
    {
    if (PolicyDetailLoadError != null)
    PolicyDetailLoadError(this, new EventArgs());
    }
    };

    client.GetPolicyDetailAsync();
    }

    The event handler is right in-line with the loading function. The event args remain strongly typed, so you have access to everything you normally would with an additional function.

  • Persisted Properties

    Back in classic ASP.NET I’d persist data extract from a web service in base class property as follows:

    private string m_stringData;
    public string _stringData
    { get {
    if (m_stringData==null)
    {
    //fetch data from my web service
    m_stringData = ws.FetchData()
    }
    return m_stringData;
    }
    }

    This way I could always simple use _stringData and know that I’d always get the data I was after (sometimes I’d use Session state as a store instead of a private member variable).

    In Silverlight with a WCF this doesn’t work, because the WCF service has to be called asynchronously.

    So, how do I get round this?… There are a number of routes to take. One method involves wrapping the messages synchronously and can be found at codeplex

    Another alternative that is less verbose, and arguably easier, to follow is using a lambda expression as follows:

    private string m_stringData;
    public string _stringData
    {
    get
    { //if we don't have a list of departments, fetch from WCF
    if (m_stringData == null)
    {
    StringServiceClient client = new StringServiceClient();
    client.GetStringCompleted +=
    (sender, e) =>
    {
    m_stringData = e.Result;
    };
    client.GetStringAsync();
    }

    return m_stringData;
    }
    }

    A final solution was posted on this stackoverflow thread