Category Archives: WPF

We build framework, you build application.

This should be the motto for Microsoft, and any framework provider. But thing is different in WPF world, try google how many people are working so hard to make ListView header click sortable.

I don’t like code behind, the classic event hook up isn’t a clean solution at all. There are a few smart guys using attached property to implement this sort feature, xaml can be much simpler, and we can slowly build our own WPF framewrok extension. (?)

The idea can be found from this post, but the attached source code are missing, this post uses same technology with full version of source code. In fact, I think Thomas’ solution is better, he is using a technique called Adorner, which is cleaner than the other one using switching template. The only part I don’t like is the extra GridViewSort.PropertyName in his xmal to set the sorting property name. Why not just use the native binding name? like this:

propertyName = ((System.Windows.Data.Binding)headerClicked.Column.DisplayMemberBinding).Path.Path;

That’s for click-header-sorting.

How about double-click to trigger event/command in view model? Check this post.

Is there an open source project somewhere called WPF contrib? Yes, check out the WPF tool kit on codeplex, at least the click-header-sorting is supported, including some other fancy feature, such as the alternate row color.

We use Evil Attribute library in our service and UI/ViewModel to do validation on DTO, the big advantage is centralizing the validation rules. One challenge left is how to enable WPF Forms dynamically showing the error message, like ajax doing on web.

Found a very smart and simple solution for this, what we need to do is simply to wrap the Evil ValidationErrors in WPF ValidationRule class.

<Window.Resources>
 <ControlTemplate x:Key="TextBoxErrorTemplate">
 <StackPanel>
 <StackPanel Orientation="Horizontal">
 <Image Height="16" Margin="0,0,5,0"
 Source="warning_48.png"/>
 <AdornedElementPlaceholder x:Name="Holder"/>
 </StackPanel>
 <Label Foreground="Red" Content="{Binding ElementName=Holder,
 Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"/>
 </StackPanel>
 </ControlTemplate>
 </Window.Resources>
 <Grid>
    ...

  <TextBox Height="23" Margin="35,9,77,0" Name="textBox1" VerticalAlignment="Top"
     KeyUp="OnTextBoxKeyUp"
     Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}">
     <TextBox.Text>
    <Binding ElementName="listBox1" Path="SelectedItem" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <ViewModels:EmailRoleRule />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
 </TextBox>

public class EmailRoleRule : ValidationRule
 {
  public override ValidationResult Validate(object value, CultureInfo cultureInfo)
   {
   var roleName = (string) value;
   var validator = new EvilValidator(new EmailRoleDto() { Name = roleName });
   if (validator.IsValid())
   {
    return new ValidationResult(true, null);
   }
   return new ValidationResult(false, string.Join("\n", validator.ValidationErrors.ToArray()));
  }
 }

wpf_validation

This technoque is actually described on MSDN.

Here is a post talking about the same skill but takes advantage of tooltips, pretty close to CSLA content control.

Found this neat feature from Jonas’ ppt. What a great feature from WPF data-binding! See page 18.

The app.main() is gone in default auto-gened WPF application, there are some workarounds to add customized startup app class. I found adding Startup attribute then implement startup eventhandler is a eaiser and clean solution:

Adding Startup property to App.xaml:
<Application x:Class=”StakeholderDemo.Layers.WpfUI.App”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
Startup=”App_StartUp”
StartupUri=”MenuForm.xaml”
>
<Application.Resources>

</Application.Resources>
</Application>

Implement code:
public partial class App : Application
{

void App_StartUp(object sender, StartupEventArgs e)
{
ObjectFactory.Initialize(x => x.AddRegistry<WpfClientDependencyRegistry>());
}

From MSDN, unhandledExcpetion can be handled genereally in application.xaml,

<Application
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.App"
  StartupUri="MainWindow.xaml"
  DispatcherUnhandledException="App_DispatcherUnhandledException" />

using System.Windows; // Application
using System.Windows.Threading; // DispatcherUnhandledExceptionEventArgs

namespace SDKSample
{
    public partial class App : Application
    {
        void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            // Process unhandled exception

...

            // Prevent default unhandled exception processing
            e.Handled = true;
        }
    }
}

I like this very much, but suggestion from IglooCoder is, you don’t want set Handled=true, the UnHandleException should keep unhanded in this UnhandledException event, for specific exception you want to handle, do it on screen or somewhere else, like local WcfProxy. This event should be the place you want to display error or log or send screen shot to admin. Anyway, exceptions shouldn’t be handled here.