Tuesday, February 16, 2010

Blend throwing System.MissingMethodException with custom-made Sample Data

Blend 3 has a pretty cool new feature called Sample Data. It's great for quickly building some design-time data that can be displayed in the design view and give the developer/designer a good idea of what the screen will look like at run-time (with a few quirks here and there).

Personally though, for developing a real application I don't like it much. It's cumbersome having to use the Blend UI for building the data when compared to the speed with which it can be accomplished writing a few lines of code. The UI has limitations too, for example, when creating a sample data object with several properties of the same complex data type. You can spend hours in the UI fiddling around with the data doing something that you could accomplish in code in minutes... or less. Additionally, you do additional things such as defining commands in your sample data, which you can quickly set breakpoints on when you run a test harness and confirm that your databindings are working correctly.

Oh, and don't ever try fiddingly around with the generated code for the sample data. You'll get bitten, trust me.

However, for our interaction designers here, it's absolutely perfect for their rapid prototypes they want to show to the client. Considering they also don't have much of a clue about coding in .NET and it's pretty much a no-brainer.

That said, for our actual implementation I prefer that our team hand write the sample data. Ultimately it's quicker.

That leads me to a problem I spent the entirety of the last day on at work. During design-time, Blend starting throwing System.MissingMethodExceptions, and the design-time data on some controls was not working. Attaching Blend to the Visual Studio debugger revealed that when loading the offending XAML file, .NET was complaining of the type being declared in multiple DLLs.

Turns out the problem (it appears) was to do with the fact that the project in question is targeted at both WPF and Silverlight, with both projects in the same solution (and using the P&P Project Linker to help manage the shared code). Since both project haves some DLLs with exactly the same name (in this case, the Models DLL that is generated from the WCF service's WSDL) Blend was getting confused. In the end I saw no alternative other than to separate the WPF and Silverlight projects into separate solution files. The problem disappeared immediately

Oddly enough, I couldn't find anything about this anywhere on the web. So I figured I'd write about it here before I forget about it and wonder why things had been split into separate solutions.

Monday, February 8, 2010

Why are we using Silverlight at Work?

I had to remind myself today how it actually came to be that we had adopted Silverlight at work. Not because I'm wishing we hadn't mind you, but just because we're about to go back and evaluate technologies again (well, we are if it can't be avoided, it's madness if we do I think) and I thought I'd better make sure I'm covered if I start getting grilled on why we took this direction in the first place. So here's how it happened, in a seriously abridged format:

Why is Silverlight/WPF our chosen platform?
Outcome of the capability enhancement project in 2008.

How was it an outcome of that project?
Various platforms were rapidly assessed for further investigation against a large number of criteria. Microsoft platforms were chosen due to time constraints and due to our existing large investment in this area. WPF came out on top, Silverlight next. This report is available in the electronic libary.

The chosen technology was investigated, architectures assessed, proofs of concept conducted, standards/guidelines developed. They were then used in our next two UI projects with a good level of success. Silverlight 4 delivers further benefits making it a better fit than it did before. Indeed, the WPF project that integrated tightly with Office and the desktop could have been written in Silverlight 4 had it been available.

Why not use an HTML based solution?
Products like one of those developed that integrate tightly with the desktop do not lend themselves to browser based solutions. By using Silverlight we can adopt a consistent architecture that brings the power of tight desktop integration with the ease of web based deployment. Adopting HTML based solutions we will still need a desktop architecture for products that require privileged access to local resources. By using Silverlight we can realise considerable savings by adopting an architecture that fits both needs.

Additional benefits
  • Tools are free (i.e. included in existing licence agreements with Microsoft)
  • Technology based on .NET/C# which we are already heavily invested in
  • Silverlight is rapidly growing with many new features being added to Silverlight 4 less than 12 months after the release of Silverlight 3. Features such as trusted applications will allow us to use a single architecture to tackle almost any conceivable business requirement

Tuesday, February 2, 2010

Sharing ViewModel Data in a Decentralised Way

Yesterday I asked some colleagues to give me some constructive feedback on my last two posts about using an Observer pattern to share ViewModel data within a Prism Module. One comment was that it would be nice to have something sharing the data in a decentralised manner using Prism's EventAggregator.

This got me thinking that this sounded like a good idea. Eventually however I remembered that I'd considered this a while ago (but had subsequently forgotten about it, should have made an blog entry!) The reason I didn't pursue this approach for long was that I was concerned about how ViewModels would be initialised with the shared data values.

For example, imagine an application that has several ViewModels all using the EventAggregator to communicate to each other about changes in a shared piece of data. Imagine now that the user initiates an action that instantiates a new instance of another ViewModel to come online (for example, they have just clicked the Next button in a Wizard style workflow). How would this new ViewModel determine the current value of the shared data?

Try as I might, I couldn't see a nice way to do this. The ViewModel could raise an event asking what the value is, but then who should reply? Since the data has no "home" per se, there is no single definitive source that can supply an answer. Ultimately it would decsend into a pile of spaghetti for anything but the simplest of situations.

Now, this is not to say that there is not good way to do it. I just couldn't think of one. In the end, I like the Observer, as it gives the data a home, a place to live, which is nice.

Monday, February 1, 2010

Using the Observable Object for Change Notification in Calculated/Dependent Properties

Extending on my previous post, how could the Observable be employed when there are dependent/calculated properties that rely on the shared data inside the observable object?

Imagine a situation where the UI contains a drop down list whose selected index is databound to an Observable Object. Next to the drop down list is an info box that is visible only when a value in the list is selected. The visibility of the info box will be bound to a calculated property on the ViewModel, whose value is dependent on the value in the observable object. Therefore, if the value in the observable object changes, the visibility value needs to change too, and the View notified.

In the simplest case where there is no shared data and an observable object is not used, the XAML for an app such as this may look like this):

<ComboBox
Width="150"
Height="22"
Margin="5"
VerticalAlignment="Top"
HorizontalAlignment="Left"
ItemsSource="{Binding Contacts}"
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"
ItemTemplate="{StaticResource _itemTemplate}"
/>
<StackPanel Orientation="Vertical" Visibility="{Binding IsConfirmSelectionVisible, Converter={StaticResource VisibleIfTrue}}">
<TextBlock Margin="5" Text="Is this the correct selection?" />
<TextBlock Margin="5" Text="{Binding SelectedContact.SelectedContact.ContactId}" />


The ViewModel may look like this:

public int SelectedIndex
{
get
{
return _selectedIndex;
}
set
{
_selectedIndex = value;
RaisePropertyChanged("SelectedIndex");
RaisePropertyChanged("IsConfirmSelectionVisible");
}
}

public bool IsConfirmSelectionVisible
{
get
{
return SelectedIndex != -1;
}
}



Nice and simple. However, what if the SelectedIndex was a shared value between multiple ViewModels? As described in the previous post, a good method for doing this is to implement an Observable. The XAML would then look like this (the selected index property of the ComboBox is altered to use an Observable Object:

<ComboBox
Width="150"
Height="22"
Margin="5"
VerticalAlignment="Top"
HorizontalAlignment="Left"
ItemsSource="{Binding Contacts}"
SelectedIndex="{Binding SelectedIndexObservable.SelectedIndex, Mode=TwoWay}"
ItemTemplate="{StaticResource _itemTemplate}"
/>
<StackPanel Orientation="Vertical" Visibility="{Binding IsConfirmSelectionVisible, Converter={StaticResource VisibleIfTrue}}">
<TextBlock Margin="5" Text="Is this the correct selection?" />
<TextBlock Margin="5" Text="{Binding SelectedContact.SelectedContact.ContactId}" />



And the ViewModel like this:

public int SelectedIndexObservable
{
get
{
return _selectedIndexObservable;
}
set
{
_selectedIndexObservable = value;
RaisePropertyChanged("SelectedIndexObservable");
}
}

public bool IsConfirmSelectionVisible
{
get
{
return SelectedIndex != -1;
}
}


The problem here now is that when the SelectedIndex property is updated, the change notification will no longer work, as the change is occuring inside the observable. Raising the property changed event for IsConfirmSelectionVisible in there will not propogate to the UI. The way I see it, there are two options:

Option 1: Move IsConfirmSelectionVisible to the Observable

The property IsConfirmSelectionVisible is moved to the observable and the XAML for the StatckPanel's Visibility property is updated accordingly. Although this results in a minimal amount of additional code it is unclean in that code specifically intended for a View has been relocated into a shared resource (the Observable).

Option 2: Listen for changes in the Observable and React

In this scenario, when the Observable is injected into the ViewModel via the constructor, the ViewModel attaches itself to it and listens for property changed events. The code might look like this:

public SelectionViewModel
(
ISelectionView selectionView,
ISelectedContactObservable selectedContactObservable
)
{
...
View = selectionView;
View.ViewModel = this;

...

// Listen for property change events on the selected contact,
// as this controls whether some parts of the UI are visible or hidden
selectedContactObservable.PropertyChanged += HandleSelectedContactPropertyChanged;
...
}


Inside the HandleSelectedContactPropertyChanged event, the event is examined and the ViewModel reacts accordingly to notify the View of any relevant changes. The code might look like this:

private void HandleSelectedContactPropertyChanged
(
object sender,
PropertyChangedEventArgs args
)
{
switch (args.PropertyName)
{
case "SelectedIndex":
RaisePropertyChanged("IsConfirmSelectionVisible");
break;
default:
break;
}
}


This option requires additional code and some event wire-up. However, it maintains a better separation of concern between the View specific code and the shared Observable implementation.

Conclusion

Despite the requirement for some additional code, Option 2 is my preferred choice due to the better separation of concerns.

A working simple example of this is available in this example Silverlight project.