Monday, August 20, 2012

Using Telerik, what is the proper way to bind a DelegateCommand to a GridViewBoundColumnBase?

Using Telerik, what is the proper way to bind a DelegateCommand to a GridViewBoundColumnBase?

In a Silverlight / Prism / MVVM application, my UI/xaml looks like this:

 <Parts:EntityLookupColumn MinWidth="150" Header="Assets"                                        EntityLookupCommand="{Binding AssetLookupCommand}"                                       DataMemberBinding="{Binding Path=AssetName}"                                        EditModeDisplayPropertyPath="AssetName"                                       SortMemberPath="Asset.Name"                                       EditTriggers="{Binding CanEdit, Converter={StaticResource BooleanConverter}}">                     <Parts:EntityLookupColumn.FilteringControl>                         <filter:CompositeFilterView >                             <filter:CompositeFilterView.FilterItems>                                 <filter:TextFilterItem Caption="Name" DataMemberPath="Asset.Name" />                             </filter:CompositeFilterView.FilterItems>                         </filter:CompositeFilterView>                     </Parts:EntityLookupColumn.FilteringControl>                 </Parts:EntityLookupColumn> 

Where the AssetLookupCommand is defined in the ViewModel:

private DelegateCommand assetLookupCommand;     public DelegateCommand AssetLookupCommand     {         get { return assetLookupCommand ?? (assetLookupCommand = new DelegateCommand(BeginAssetLookup)); }     } 

EntityLookupColumn is a GridViewBoundColumnBase

public class EntityLookupColumn : GridViewBoundColumnBase {     public override FrameworkElement CreateCellEditElement(GridViewCell cell, object dataItem)     {         var cellEditElement = new EntityLookupControl();         Binding valueBinding = this.CreateValueBinding();          cellEditElement.SetBinding(EntityLookupControl.EntityProperty, valueBinding);         cellEditElement.EntityLookupCommand = EntityLookupCommand;          cellEditElement.txtDisplay.DataContext = dataItem;         cellEditElement.txtDisplay.SetBinding(TextBlock.TextProperty, CreateEditModeDisplayTextBinding());         return cellEditElement as FrameworkElement;     }      private Binding CreateValueBinding()     {         var valueBinding = new Binding                                {                                    Mode = BindingMode.TwoWay,                                    NotifyOnValidationError = true,                                    ValidatesOnExceptions = true,                                    UpdateSourceTrigger = UpdateSourceTrigger.Explicit,                                    Path = new PropertyPath(DataMemberBinding.Path.Path)                                };         return valueBinding;     }      private Binding CreateEditModeDisplayTextBinding()     {         var binding = new Binding         {             Mode = BindingMode.TwoWay,             NotifyOnValidationError = true,             ValidatesOnExceptions = true,             UpdateSourceTrigger = UpdateSourceTrigger.Explicit,             Path = new PropertyPath(EditModeDisplayPropertyPath)         };         return binding;     }       public override void CopyPropertiesFrom(GridViewColumn source)     {         base.CopyPropertiesFrom(source);         var entityPickerColumn = source as EntityLookupColumn;         if (entityPickerColumn != null)         {             this.Entity = entityPickerColumn.Entity;             this.EntityLookupCommand = entityPickerColumn.EntityLookupCommand;             this.EditModeDisplayPropertyPath = entityPickerColumn.EditModeDisplayPropertyPath;         }     }      public object Entity     {         get         {             return GetValue(EntityProperty);         }         set         {             SetValue(EntityProperty, value);         }     }      public static readonly DependencyProperty EntityProperty = DependencyProperty.Register("Entity",         typeof(object),         typeof(EntityLookupColumn),         new PropertyMetadata(null));       public DelegateCommand EntityLookupCommand     {         get { return (DelegateCommand)GetValue(EntityLookupCommandProperty); }         set { SetValue(EntityLookupCommandProperty, value); }     }      public static readonly DependencyProperty EntityLookupCommandProperty = DependencyProperty.Register("EntityLookupCommand",         typeof(DelegateCommand),         typeof(EntityLookupColumn),         new PropertyMetadata(null));      public string EditModeDisplayPropertyPath     {         get         {             return (string)GetValue(EditModeDisplayPropertyPathProperty);         }         set         {             SetValue(EditModeDisplayPropertyPathProperty, value);         }     }      public static readonly DependencyProperty EditModeDisplayPropertyPathProperty = DependencyProperty.Register("EditModeDisplayPropertyPath",         typeof(string),         typeof(EntityLookupColumn),         new PropertyMetadata(null)); } 

that creates an EntityLookupControl:

public partial class EntityLookupControl : UserControl {     public EntityLookupControl()     {         InitializeComponent();         DataContext = this;     }      public object Entity     {         get         {             return GetValue(EntityProperty);         }         set         {             SetValue(EntityProperty, value);         }     }      public static readonly DependencyProperty EntityProperty = DependencyProperty.Register("Entity",         typeof(object),         typeof(EntityLookupControl),         new PropertyMetadata(null));       public DelegateCommand EntityLookupCommand     {         get { return (DelegateCommand)GetValue(EntityLookupCommandProperty); }         set { SetValue(EntityLookupCommandProperty, value); }     }      public static readonly DependencyProperty EntityLookupCommandProperty = DependencyProperty.Register("EntityLookupCommand",         typeof(DelegateCommand),         typeof(EntityLookupControl),         new PropertyMetadata(null));       public string EditModeDisplayPropertyPath     {         get         {             return (string)GetValue(EditModeDisplayPropertyPathProperty);         }         set         {             SetValue(EditModeDisplayPropertyPathProperty, value);         }     }      public static readonly DependencyProperty EditModeDisplayPropertyPathProperty = DependencyProperty.Register("EditModeDisplayPropertyPath",         typeof(string),         typeof(EntityLookupControl),         new PropertyMetadata(null)); } 

Recently, we upgraded Telerik and Silverlight to the latest version. Before the upgrade, AssetLookupCommand was bound to the EntityLookupColumn's EntityLookupCommand, and so BeginAssetLookup would execute when expected (When EntityLookupColumn's CreateCellEditElement was called, EntityLookupCommand was never null). But now, AssetLookupCommand is not bound until sometime later (now CreateCellEditElement assigns cellEditElement.EntityLookupCommand to a null value). I have to click on this column, then click on a different column (can be even in a different row), and then click back on this column again to set AssetLookupCommand, and cause EntityLookupCommand to stop being null.

I'm wondering if the original design is flawed, and needs to be revisited. Or maybe Telerik made some enhancements, which affected some of the wiring, and now I need to hook things up in a different manner.

Answers & Comments...




No comments:

Post a Comment

Send us your comment related to the topic mentioned on the blog