DevWeek08
I went to DevWeek08 this week, and saw some excellent presentations, and some not so….
I particularly liked the talks by Christian Weyer and Richard Blewett on .Net 3.5
However, there wasn’t a huge amount of WPF stuff. I saw a couple of talks by David Wheeler, just to see how it was panning out in the real world. They were very popular, so I wonder if the organisers might have put on more WPF talks. One of the talks was on multi-threading in WPF, and Dave was a very entertaining talker although the content wasn’t that deep due to time constraints.
Silverlight was overshadowing WPF, as I suspect it will in the general world of IT 🙂
The talks on Silverlight by Jeff Prosise were also excellent, and his enthusiasm for the subject matter was clear.
It has made me realise two things that I didn’t know:
1. A beta of Silverlight was released last week (for MIX08 in USA I believe), and actually has some decent stuff in it. And it works 🙂
2. It really is cool :-), so I think I might do some posts on the experienc
Re-using data template across controls
How do you use the same data template across different types of control?
Well you can 🙂
Normally when you define the data template, you do something like the following:
<DataTemplate DataType=”{x:Type ListViewItem}>
<TextBlock Text=”{Binding Path=ISIN}” />
</DataTemplate>
However, it is a bit of a pain to then copy it for different types, but there is a way:
<DataTemplate DataType=”{x:Type local:Instrument}>
<TextBlock Text=”{Binding Path=ISIN}” />
</DataTemplate>
(where Instrument is a class in your assembly)
This template can now be used with any control type.
Multi value converter in databinding
Here’s a nifty little trick that I recently discovered.
When you need to calculate the result of two properties and display it, you can do it via a Converter class.
You may want to do it, like me, if you couldn’t update the business objects, or didn’t want to.
How do you do it?
Your converter class needs to implement IMultiValueConverter instead of IValueConverter.
E.g.:
Then you specify a multi binding in your xaml, like:
Explicit control of how the source is updated
In a previous post, I described how you can get a binding to update in real time – i.e. as you type.
Sometimes however, you want to control the updating more closely, i.e. in code. For example, you may want to do the update only when a timer has ticked.
There is a little used argument for UpdateSourceTrigger (well in 18 months of using WPF I’ve never seen it used :-)) , namely Explicit that allows you to do that.
Given some xaml like:
<ComboBox Name=”cbUsers” SelectedValuePath=”Name” />
<TextBox Name=”tbUserName” Text=”{Binding ElementName=cbUsers, Path=SelectedValue}” />
When you add UpdateSourceTrigger=Explicit to the TextBox, you can control the updating by telling the binding mechanism to update.
<TextBox Name=”tbUserName” Text=”{Binding ElementName=cbUsers, Path=SelectedValue, UpdateSourceTrigger=Explicit}” />
How do you do that? That’s where the magic lies 🙂
You need to get the BindingExpression for the TextBox:
BindingExpression binding = tbUserName.GetBindingExpression(TextBox.TextProperty);
Then update the linked source( the textbox):
binding.UpdateSource();
bingo
Controlling how the source is updated in a binding
Have you ever wondered how to alter the update frequency of a binding?
Probrably like me, you use the default settings unless you notice something not working
🙂
What am I talking about?
Well, when you have a binding defined to another element for example:
<TextBox Name=”txtFirstOne” />
<TextBox Text=”{Binding ElementName=txtFirstOne, Path=Length” Name=”txtFontSize” />
The second textbox will display the length of the text in the first textbox, as you type. Well actually it doesn’t, as the target is not being updated. To fix that you could add UpdateSourceTrigger=PropertyChanged for this example, and bingo:
<TextBox Text=”{Binding ElementName=txtFirstOne, Path=Length, UpdateSourceTrigger=PropertyChanged” Name=”txtFontSize” />
Save ObservableCollection to Linq for Sql
I described how you create an ObservableCollection from a Linq query (including Linq for Sql amongst others) in a previous post.
A second part of the equation is of course, how do you then save your changes back to the database using Linq?
Of course, you have probrably guessed that it’s not going to be a walk in the park.
What you need to do is go through the object and all sub lists and convert them back into the Linq EntitySet classes. After that they can be saved via SubmitChanges.
Tedious, you bet!
Either I’m missing the point somewhere or the EntityFramework needs to fix this by implementing INotifyCollectionChanged in the EntitySet class
Creating an ObservableCollection from Linq for Sql
Just how do you create an ObservableCollection from a Linq query?
Not easily is the answer.
If you are using WCF as part of your multi-tier strategy, then you can employ a trick that converts your generated Linq for Sql EntitySet classes into ObservableCollection classes. See a previous post of mine for details.
If you are not using WCF, then like me you’re a bit stuck – you seem to have to do it manually. For each access you need to convert it to a non Linq business object class, and crucially all it’s properties that contain lists.
I have here an example from the AdventureWorks database where the Products List is populated from the database into a ProductModel class, and I show how to do this with a couple of sub properties and one sub list (ProductCostHistories).
First here is the Product class, which is a separate class from the Linq generated Product class:
Here is the ProductModel class which does the interaction with Linq:
WPF validation via databinding
With v3.5 of the .Net framework, you can now take advantage of the new (well actually quite old) automatic error/validation mechanism.
What do I mean by new/old? I mean that by implementing the IDataErrorInfo interface you can plug into the .Net 3.5 error/validation. When you provide information to the methods of the interface, and tell the WPF binding mechanism to use it, it will magically display a red rectangle around the bound control by specifying the ValidatesOnDataErrors=True binding extension.
An example always helps, so here I have a class that implements the IDataErrorInfo interface:
It provides the this[string propertyName] override. This indexed property gets called by the framework every time a property is updated. This gives you the opportunity to add validation on a per property basis. The interface also has another property Error, which you typically call all of the property validators to get an overall validation message.
Databinding with Linq with automatic updates
How do you databind to an EntitySet retreived from a Linq query, via Linq to Sql or Linq to Entities for example?
Well it is very easy to actually bind to it, you simply connect it up using normal Xaml syntax. But what if you want to have updates automatically relected in the UI? That’s something that ObservableCollection does very well, due to it’s implementation of INotifyCollectionChanged. So why didn’t they implement INotifyCollectionChanged in the EntitySet class? Who knows? It would have saved me a load of grief, for starters.
For a list of your different options, see a previous post of mine.
Here I will show how I have got around the problem:
I have a database table called Profiles, which using the Linq for Sql visual designer gives me a class called ProfilePart. As it is a partial class I can have another cs file with my ProfilePart definition and provide my binding implementation.
How do I it? I call the GetNewBindingList() method on the EntitySet, but I need to cache it as I don’t want to do it every time it is accessed.
An example is shown below:
WPF databinding to Linq
I think I have (at last) the workaround that gets WPF to bind to objects from Linq (to SQL or Entities or anything…)
The problem is that Linq’s EntitySet class doesn’t implement INotifyCollectionChanged, so when you bind to an object that contains child collection classes you don’t get automatic notification of changes to your collection.
You basically have four choices:
- Use a framework like CSLA (and I’m going to look a lot more closely at the v3 of CSLA which supports WPF)
- Create another class (and all child classes) and copy data out of the EntitySet into the new class and put that in an ObservableCollection. Then when you save copy it back into a new Linq DataContext (and all the child classes) – do you think yuk like me?
- Bind the control to the EntitySet’s GetNewBindingList(), which will dynamically update the control for you
- Create a BindingSource object and set it’s DataSource to the EntitySet’s GetNewBindingList() call and then bind the control to the BindingSource
Which you choose depends on the circumstances though of course