Presentation Model Pattern Question

Nov 26, 2008 at 3:01 AM
Edited Nov 26, 2008 at 3:16 AM
Hello,

I have a general question about the Presentation Model Pattern. It seems to me that basic scenarios are not addressed in the supplied sample application. At least I can't find it. I am hoping someone here can give me a nudge in the right direction.

Say I have a view called Customers.xaml that displays a list of customers in a GridView. I need the grid to be sorted but 'CustomerName'. In order to do this in the typical way, I need to handle the GridViewColumnHeader.Click event. This however requires the event handler to be placed in the code behind. I suppose I could define the handler in the PresentationModel and bind to it, however this would then tightly couple the PresentationModel to very view centric objects.  See  below.


//Example of why it would be bad in the PresentationModel Class
void
GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e)
{
    //Presentation Model should not know about GridViews etc...
    GridViewHeader selectedHeader = e.OriginalSource as GridViewHeader;
}

 

That being said, it seems to me to make the most sense to handle the event in the code behind, and then to delegate anything needed to the Presentation Model. See below.

//Code behind example
void
GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e)
{
     //Code Behind handles it
    GridViewHeader selectedHeader = e.OriginalSource as GridViewHeader;
    
    PresentationModel viewModel = DataContext as PresentationModel;
    ViewModel.Sort(selectedHeader.Text);
}

So I guess my question is basically if this is ok or if I am totally missing something? I was pretty disappointed that the Sample Application left out some of this basic stuff. Perhaps I just missed it in there. Any insight in to this would be very much appreciated.

Thanks,
Brette

 

Nov 26, 2008 at 12:32 PM
Hi Brette21,

You're right, you should not place logic on your ViewModel that access your UI controls directly. The second approach looks much cleaner than the first one.

Another approach if you didn't want to have code behind at all, is to use the AttachedBehavior pattern, where by setting an attached property (of type ICommand for example) on the GridViewHeader, you subscribe to the Click event, and end up executing the command which will be bound to the ViewModel.
You can see an example of an Attached Behavior in the following post (which is actually implemmenting commands for buttons in Silverlight, but the same thing applies to WPF, and if you replace ButtonBase for a GridViewHeader or something more generic, it should work directly):

By the way, did you check out the new DataGrid control included in the WPF Toolkit? It is much powerful and easy to use than the GridView, and has sort features already built-in. These controls will be part of the framework in the future.

Let me know if this helps,
Julian Dominguez
http://blogs.southworks.net/jdominguez
Nov 26, 2008 at 2:36 PM
Hey Julian,

First thanks for the great response. I will look at the AttachedBehavior pattern per your suggestion. I seem to recall reading that some time ago however at the time, I did not really understand why it was useful. I suppose this points it out rather clearly now! So Thanks!

You mentioned the WPF Toolkit. Indeed I have looked at this, and I was very excited for it to arrive in Oct. However I did run into an issue that I am currently unable to resolve. When I add the following grid to my xaml file it works just fine.

<my:DataGrid Name="dataGrid1" VerticalAlignment="Bottom" xmlns:my="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit">
</my:DataGrid>  


However this is not a very useful grid. Sadly when I add any column to the grid definition my app locks up. I am not really sure if focus is just lost, or if some thread is blocking or if there some other issue in my project or the grid that is causing it. I get no error messages to investigate, and when I look at the running threads there does not seem to be any blocking going on. In any case it renders my application for all practical purposes unresponsive. Here is the code that will cause this behavior.

<

 

my:DataGrid Name="dataGrid1" VerticalAlignment="Bottom" xmlns:my="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit">
    <my:DataGrid.Columns>
        <my:DataGridTextColumn Header="Header" />
    </my:DataGrid.Columns>
</my:DataGrid>

 

 

We all know that no application can function without at least one grid that with one unbound column with a title of 'Header' so I have had to go back to the old fashioned way of using a ListView and a GridView. This made me very sad. And even though this happened long long ago (yesterday) the pain is still fresh in my mind. ;-)


Brette

Nov 26, 2008 at 3:09 PM
Hi,

I'm glad you found the link useful.

Regarding the DataGrid, I tried your markup on an empty Window, and I did not have any issues with it. It doesn't do much, but the application does not lock up. Maybe you should give it another try, it will make your life easier in the future ;-)

Julian
Nov 26, 2008 at 4:34 PM
You are correct. In fact if I create a simple project with a new window, I can get it to function as well. However for some reason in the context of the current application I am working on, things go bad for me. I will prolly take another look this weekend. In any case the Attached Behavior Pattern was very helpful indeed. Thanks!

Brette