Friday, August 14, 2009

Based on my recent posts regarding Silverlight, MVVM and invoking methods on arbitrary target objects, a couple people suggested that behaviors or trigger actions might be a good solution.

These are new concepts introduced through the System.Windows.Interaction assembly that comes with Expression Blend 3. That’s somewhat of a drawback, since this means a developer is required to install Blend 3 to get the assembly before these features are available. It would be nicer if they were part of the standard Silverlight (and WPF) development platform.

The other challenge I’ve encountered in working with this technology is a limitation when it comes to data binding. Silverlight only full binds with dependency properties of FrameworkElement objects. Since classes like TriggerAction<T> don’t inherit from FrameworkElement, their dependency properties aren’t bindable. This means you can’t define a property on a trigger and then bind it to other elements in the UI, which is really an unfortunate limitation.

For example, I created an Execute trigger action that defines MethodName and MethodParameter properties. If I have a ListBox and a Button, and I want the Button to trigger some method that acts on the SelectedItem property of the ListBox, what I’d really like to do is this:

<Button Content="Refresh">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
      <csla:Execute MethodName="Load" MethodParameter="{Binding ElementName=MyListBox, Path=SelectedItem}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

(in this code the ‘i’ prefix refers to System.Windows.Interactivity from Blend 3 and the ‘csla’ prefix refers to Csla.Silverlight from CSLA .NET)

Unfortunately this won’t get past the Silverlight XAML parser, because a binding expression isn’t allowed for MethodParameter…

I also wanted to implement a MethodTarget property so the Execute trigger could invoke methods on some object other than the current DataContext. Unfortunately that puts us back to needed the ability to use binding to specify the value of MethodTarget, which isn’t possible. So my current implementation can only invoke methods on the DataContext of the associated control (the Button in this case).

To get around the MethodParameter limitation I’m using a Tag hack

<Button Content="Refresh" Tag="{Binding ElementName=NewIdTextBox, Path=Text}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
      <csla:Execute MethodName="Load" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

When the Execute trigger invokes the method, it passes an ExecuteEventArgs parameter to the method, which includes a TriggerSource property of type FrameworkElement. This means the method, in the view model class, can access the Tag property of the associated control (the Button), which can be bound because the Button is a FrameworkElement:

public void Load(object sender, ExecuteEventArgs e)
{
  var tag = e.TriggerSource.Tag.ToString();
  int id = 0;
  if (!string.IsNullOrEmpty(tag))
    id = int.Parse(tag);
  Load(id);
}

Sure this is somewhat hacky, but since the trigger action can’t define bindable properties of its own, this seems like a workable solution.

Friday, August 14, 2009 12:44:31 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, August 13, 2009

CSLA .NET 3.6 normally requires .NET 3.5 SP1. However, if you are using Visual Studio 2008 it is possible (with some work and a third party LINQ library) to get CSLA .NET 3.6 running on .NET 2.0 SP1. Jonny Bekkum has done just that, and has contributed the results of his efforts to the community - thank you Jonny!

The result is a large subset of version 3.6.3 that builds and runs on .NET 2.0 SP1, eliminating the need for .NET 3.5 SP1 (though adding the need for LINQbridge, a third-party component).

You get to use the most of the new features in CSLA .NET, including:

  1. Managed properties in BusinessBase, ReadOnlyBase and CommandBase that reduces the number of lines required to declare a property.
  2. PropertyInfo type for less hardcoding of property names in your code.
  3. FieldManager and DataPortal enhancements, including the asynchronous DataPortal and Child_XYZ mehthods.
  4. ObjectFactory for separation of BO and DAL
  5. CslaActionExtender reduces the amount of code behind required in Windows Forms
  6. Reflection enhancements (MethodCaller) for dynamic calls
  7. An easier upgrade path to CSLA .NET 3.7 and Silverlight
  8. and a lot more ….

Jonny has not only got the CSLA .NET framework running on .NET 2.0, but he’s got unit tests and samples! This is an amazing contribution to the community.

You can download this version from http://www.lhotka.net/cslanet/N2.aspx.

Thursday, August 13, 2009 10:33:45 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, August 07, 2009

Welcome to the August edition of our Webinar Schedule!
We are pleased to introduce a series of exciting new webinars! For the month of August, we offer webinars on what Metrics Every Performance Testing Engagement Should Provide to Ensure Application Stability and on how to use SharePoint for Extranets. In collaboration with the Chicago Technology Executives Club, we are offering Business Dashboards - Developing a Culture of Intelligent Execution with Magenic's Dan English. In September, we begin a 5-part series on Silverlight Application Migration with Rocky Lhotka, Corey Miller, and Anthony Handley. We will cover the topics, Why Silverlight?, Windows to Silverlight, Web to Silverlight, Reimagining the UI in SIlverlight, and Silverlight: Service-oriented vs. n-tier. We are excited for you to attend these educational, cutting-edge webinars from our experts!


Magenic Webinars are complimentary and are designed as a resource for IT decision makers. Learn from our experts and have your questions ready for the Q&A at the end of each presentation. Register now for these exciting webinars!



Thursday, August 20th, 11:00 PT, 1:00 CT, 2:00 ET
Do you know how your application will perform when you go live?  Performance Testing will simulate how your application will perform with real life scenarios, enabling you to find and fix performance issues prior to launch. This will enable you eliminate risk and potential system down time, such as your customers not being able to access your website. This presentation will help guide you through the initiation, planning, and execution phases of your Performance Testing Engagement.




Thursday, August 27th, 11:00 PT, 1:00 CT, 2:00 ET
SharePoint 2007 seems to be everywhere. This webinar will offer a perspective on the key issues involved in leveraging the SharePoint platform for Extranets. Topics will include an overview and common pitfalls related to: Security, Authentication & Authorization, Architecture, Search, and Content Management.


·

We are excited to introduce our 5-part Silverlight Application Migration series beginning in September. Rocky Lhotka, Corey Miller, and Anthony Handley will be presenting this series. Click the picture above for full descriptions of each webinar and registration for the entire series or the webinars of your choice.




Wednesday, August 26th, 10:00 PT, 12:00 CT, 1:00 ET
In the current economic climate, it is more important than ever for business stakeholders to have a pulse on what is happening in their organization. Implementing an Executive Dashboard allows an organization to more effectively and efficiently execute on strategy, improve business processes and manage key company metrics proactively. This webinar is presented by Magenic's Dan English in conjunction with the Chicago Technology Executives Club.

 


Magenic Delivery Center About Us Careers Events

 

 

Friday, August 07, 2009 12:20:00 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, August 04, 2009

CSLA .NET 3.6 introduced the InvokeMethod component for Silverlight, which was intended to replace at least the basic WPF commanding functionality I tend to use to trigger actions on a CslaDataProvider when buttons are clicked. And it did that.

It turns out however, that with a few tweaks, InvokeMethod is much more broadly useful than just triggering actions on a CslaDataProvider. In a more general sense, InvokeMethod can be used to call a method on nearly any object in response to nearly any event being raised by a UI control.

I’ve been reworking InvokeMethod quite a bit over the past few days, and whatever I end up doing will be in CSLA .NET 3.8. And it will be a breaking change over the 3.6 and 3.7 functionality, which is unfortunate, but I think it is worth it.

This blog post is not the final word, just kind of a “state of the control” post to solicit thoughts and feedback as I work on version 3.8.

In the new model, InvokeMethod can still invoke methods on a CslaDataProvider, so no functionality is lost.

But in the new model, InvokeMethod can invoke methods on other arbitrary objects, as long as they can be described through a binding expression. In other words, any bindable object that has a method becomes a valid target. And the range of trigger events is much broader; in fact any event should now work, though I’ve only tested a handful of common events (click, doubleclick, selectionchanged, etc).

Using some data binding trickery I’ve made the Target property (used to be the Resource property) optional. If you don’t set the Target property, InvokeMethod will target the DataContext of the control to which it is attached. This is not so useful with a data provider model, but is very useful with a ViewModel model.

Simple scenario

So an example of triggering an action on a ViewModel when a button is clicked:

<Button Content="Refresh"
        csla:InvokeMethod.TriggerEvent="Click"
        csla:InvokeMethod.MethodName="Load" />

When the button is clicked a Load() method is invoked on the current DataContext, which is probably a ViewModel class with a Load() method:

public class DataListViewModel : CslaViewModel<DataList>
{
  public void Load()
  { 
  }
}

That’s the simplest example, and could be handled by commanding in WPF.

ListBox doubleclick scenario

A more interesting example is where the UI needs to do something in response to a doubleclick of an item in a ListBox. This is interesting because there’s a temporal issue where the user could select an item in the list, and not doubleclick on it ever, or for a long time. In my mind, the ViewModel would handle the doubleclick through a method that accepts the selected item as a parameter:

public void ProcessItem(Data item)
{
}

That implies that InvokeMethod can pass the selected item as a parameter, and in the current incarnation it can do this:

<ListBox
         ItemsSource="{Binding Path=Model}"
         ItemTemplate="{StaticResource DataList}"
         csla:InvokeMethod.TriggerEvent="MouseDoubleClick"
         csla:InvokeMethod.MethodName="ProcessItem"
         csla:InvokeMethod.MethodParameter="{Binding SelectedItem, RelativeSource={RelativeSource Self}}"/>

The ambient DataContext here is the ViewModel object, and you can see that the ListBox loads its items from the Model property (where the Model is a collection of Data objects). The only really interesting thing here is that the MethodParameter property is using binding to pick up the SelectedItem property from the UI control – so from the ListBox. This directly meets my requirement of being able to pass the selected item to the ViewModel method.

The ViewModel doesn’t care what type of UI control is used, as long as it gets a selected Data item. This also means the ViewModel is quite testable, because it is a simple method that accepts a strongly typed parameter.

MultiSelect ListBox scenario

This even works with a multiselect ListBox control (though my solution seems a bit messy).

Obviously this requires a Button or some other control outside the ListBox, since a multiselect ListBox doesn’t raise events quite the same way. The user gets to select arbitrary items in the ListBox, then click a Button to trigger processing of all selected items.

The ViewModel has a method to handle this:

public void ProcessItems(ObservableCollection<object> items)
{
}

And the XAML invokes this method from the Button (assuming the ListBox has an explicit name):

<Button Content="Process items"
        csla:InvokeMethod.TriggerEvent="Click"
        csla:InvokeMethod.MethodName="ProcessItems"
        csla:InvokeMethod.MethodParameter="{Binding ElementName=DataListBox, Path=SelectedItems}"/>

Again, the ViewModel just accepts a (relatively) strongly typed parameter, not caring about the type of UI control that generated that value. There’s no real type-level coupling between the XAML and the ViewModel.

In all these cases the XAML knows nothing more than that there’s a Model to bind to, and some actions (methods) on the ViewModel that can be invoked.

And the ViewModel knows nothing more than that it is being invoked by something. XAML, a test harness, it doesn’t really matter, it just does its thing.

Whether this is “MVVM” or not, I think it is pretty darn cool :)

Tuesday, August 04, 2009 9:30:44 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

I’m trying to do something that seems like it should be so simple and obvious.

I have an attached property, MethodParameter, which I’m applying to a Button, but I’m binding to a ListBox control:

<Button Content="Process items"
        csla:InvokeMethod.TriggerEvent="Click"
        csla:InvokeMethod.MethodName="ProcessItems"
        csla:InvokeMethod.MethodParameter="{Binding ElementName=DataListBox, Path=SelectedItems}"/>

This works, and does bind. But it appears to bind only when the Button control is instantiated, not when the Click event is handled.

In other words, the binding occurs. The user then interacts with the ListBox control and selects some items, and then clicks the Button. That triggers the Click event, which causes the InvokeMethod object to actually use the MethodParameter value.

However, at that point in time the binding appears to still be using the original collection from when the form was being loaded, and so the collection is empty.

If I actually examine the SelectedItems property it has multiple items of course – but it is a different collection than the one from when the form was loaded.

In other words, ListBox seems to create a whole new collection each time SelectedItems is invoked, and that’s apparently totally messing up data binding.

I don’t know if this problem is unique to ListBox, or if it is a broader problem with element binding, but it is making my life very unpleasant…

To solve this, I’m hijacking the binding process like this:

public static object GetMethodParameter(UIElement ctrl)
{
  var fe = ctrl as FrameworkElement;
  if (fe != null)
  {
    var be = fe.GetBindingExpression(MethodParameterProperty);
    var dataItem = be.DataItem;
    string path = be.ParentBinding.Path.Path;
    if (dataItem != null && !string.IsNullOrEmpty(path))
    {
      var pi = Csla.Reflection.MethodCaller.GetProperty(dataItem.GetType(), path);
      return Csla.Reflection.MethodCaller.GetPropertyValue(dataItem, pi);
    }
  }
  return ctrl.GetValue(MethodParameterProperty);
}

Basically I’m using reflection to manually go get the property value of the target object. This works, but feels really wrong.

If we’re dealing with a nasty idiosyncrasy of the ListBox I can probably restrict this to only be messy when talking to a ListBox control, but I rather suspect ListBox isn’t the only issue.

I’ve tried all sorts of things on the binding expression - Mode=TwoWay and BindsDirectlyToSource=True. But they had no impact. It appears that the binding gets a reference to the property value when it is created and never knows enough to re-read the value later when I actually need it.

Any ideas?

Tuesday, August 04, 2009 9:13:49 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |