Pages

Monday, October 28, 2013

How to implement a login screen in WPF

I recently needed to implement an application with login screen and googled some best practice, but without luck. I've seen some solutions, but none of them could impress me. So, I decided to do it in my way and share with you.
First of all, my prerequisites were not to use two windows, because it looks lame when WPF closes one window and starts a new one. I also didn't want to use Popups or modal dialogs because they come after main window and they are part of the it. Furthermore main window (UserControl) will be loaded, initialized and rendered before you even see a login screen. If you don't put to much logic in your constructor it might be fast, but still unwanted at that moment. So, I think the best way is to use one Window with two UserControls.

Let's start with the contents, we need a LoginViewModel and a MainViewModel. Login will be shown first and if the credentials were accepted screen will be changed to main. Create a common interface, IFrameContent with an OnChangeRequest event handler member. Implement this interface as a FrameContent base class.

public abstract class FrameContent : ViewModelBase, IFrameContent
{
   public event EventHandler OnChangeRequested;
   
   protected void Deactivate()
   {
      if (this.CanDeactivated())
      {
         var handler = OnChangeRequested;
         if (handler != null)
         {
            handler(this, EventArgs.Empty);
         }
      }
   }

   public virtual bool CanDeactivated()
   {
      return true;
   }
}      

Not a big deal. ViewModelBase is a simple base class, which implement INotifyPropertyChanged. Okay, inherit this class and create our two screens: main and login.

public class LoginViewModel : FrameContent
{      
   public RelayCommand LoginCommand { get; private set; }

   public LoginViewModel()
   {
      this.LoginCommand = new RelayCommand(Login, (p) => true);
   }

   private void Login(object parameter)
   {
      this.Deactivate();
   }
}

MainViewModel is the same story. RelayCommand is an implemented ICommand interface. In the view bind the command to a button. What here happens is a command execution without any check. But don't worry, you can extend it later.

Finally create the FrameWindow, our only window and put everything together. Create two properties for our two view models and an extra for currently selected. Subscribe their events and in the handler change to the other content.

public class FrameWindowViewModel : ViewModelBase
{
   private LoginViewModel _Login;
   private LoginViewModel Login
   {
      get
      {
         if (this._Login == null)
         {
            this._Login = new LoginViewModel();
            this._Login.OnChangeRequested += Login_LoginSuccessful;
         }

         return this._Login;
      }
   }

   private MainViewModel _Main;
   private MainViewModel Main
   {
      get
      {
         if (this._Main == null)
         {
            this._Main = new MainViewModel();
            this._Main.OnChangeRequested += Main_OnChangeRequested;
         }

         return this._Main;
      }
   }

   private IFrameContent _currentContent;
   public IFrameContent CurrentContent
   {
      get
      {
         return this._currentContent;
      }
      private set
      {
         this._currentContent = value;
         this.RaisePropertyChanged("CurrentContent");
      }
   }

   public FrameWindowViewModel()
   {         
      this.ChangeContent(this.Login);
   }

   private void Main_OnChangeRequested(object sender, EventArgs e)
   {
      ChangeContent(this.Login);
   }

   private void Login_LoginSuccessful(object sender, EventArgs e)
   {
      ChangeContent(this.Main);     
   }

   private bool ChangeContent(IFrameContent content)
   {
     this.CurrentContent = content;

     return true;
   }
}

The trick is, that you need to bind the CurrentContent in the view as a ContentPrestener's content.

<Window x:Class="LoginDemoClient.Views.FrameWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Demo client" Height="350" Width="525">

    <ContentPresenter Grid.Row="1" Content="{Binding CurrentContent}" />

</Window>

Override the CanDeactivated() method in content classes and build in some real check to prevent login in case of invalid credentials.

Of course you can (need to) extended bases classes with OnActivated(), OnDeactivated() etc methods in a real application, but the base concept does not change. You have one current content and change it in a frame window (SRP) without those two actually would known each other or without EventBus or EventAggregator (which are anti-pattern in my opinion).

You can download a full source code from here.

MDI implemention in WPF

I just recently noticed that, there is no MDI (Multiple Document Interface) support in WPF. Microsoft recommends to use TabControl or AvalonDock. However sometimes it could be really useful to see multiple documents in the same time, e.g: during data process. So I decided to develop a one. You can download MDIContainer from here. There is a sample application as well.

How to start
After you downloaded the binary (PDB is also attached), all you need to do is add MDIContainer.Control.dll as reference in your WPF Application. In order to use you need at least .NET 4. MDIContainer does not need any third party or additional references.

Hello MDI
You can decide to use direct content or bind ItemsSource to container. However direct content does not make too much sense. Why do you need closable windows if you have fixed content? So, let's stay by binding. 

<MDI:MDIContainer Margin="4" ItemsSource="{Binding Items}">
    <MDI:MDIContainer.Resources>
        <Style TargetType="{x:Type MDI:MDIWindow}">
            <Setter Property="Title" Value="{Binding Title}" />             
        </Style>
    </MDI:MDIContainer.Resources>
</MDI:MDIContainer>

As you can see, it is similar to the implementation of a TabControl. ItemsSource is also not magic, a simple ObservableCollection<IContent>. You don't have to use IContent interface if you don't want to, you can put there object or your class. It doesn't matter. I prefer to use interfaces in situations like this, to make it more flexible.

public ObservableCollection<IContent> Items { get; private set; }
 
public interface IContent
{
   string Title { get; }
}

There is only one thing left, a user control. Like I wrote, there is no limitation. Create a user control with a view model like you want. Here is a really sample one:

public class PersonWindow : ViewModelBase, IContent
{
  public string Title { get; private set; }

  public PersonWindow(string title)
  {
    this.Title = title;
  }
}

If you don't know how to implement ViewModelBase or what could it be, you can read more here. Currently you can leave it's view empty, but don't forget to set it as DataContext or DataTemplate.

Back to the main window's view model, where you defined the Items. Initialize the Items and add some content:

public MainWindowViewModel()
{
  this.Items = new ObservableCollection<IContent>();
  this.Items.Add(new PersonWindow("Window 1");
  this.Items.Add(new PersonWindow("Window 2");
  this.Items.Add(new PersonWindow("Window 3");
}

Of course this tiny little example does not make too much sense, but shows you how simple to use this control.

You can check it's CodePlex site and download a fully working demo with source code.

Thursday, October 10, 2013

How to subscribe on property changes without events

In my previous post I already explained how to implement INotifyPropertyChanged and INotifyPropertyChanging properly. At least one proper way. If you missed it, you might want to read it before this post, because this one based heavily on it. Let’s assume we want to use it as base class for our ViewModels and Models as well. In our really simple example we have a model called Person. This class is inherited from our base ViewModel (implemented in my prev. post), named  ViewModelBase.

public class Person : ViewModelBase
{
   private string _name;
   public string Name
   {
     get { return _name; }
     set { this.SetAndRaisePropertyChanged(() => this.Name, ref _name, value); }
   }

   private DateTime _birthDate;
   public string BirthDate
   {
     get { return _birthDate; }
     set { this.SetAndRaisePropertyChanged(() => this.BirthDate, ref _birthDate, value); }
   }
}
  
And a 'manager' class, our MainViewModel, also inherited from ViewModelBase. Person is bound to UI, user can create a new one, modify and existing one, it doesn't matter. Anything happens with our class Person we want to receive a notification in our MainViewModel. We can extend our base class with an OnPropertyChanged protected method, like OnPropertyChanging, but those are protected and we are in another class. We can use the PropertyChanged event, but there are two issues with it: first it is a hard reference, we need to manage subscriptions (subscribe and unsubscribe), otherwise the garbage collector (GC) won't dispose our class. Second issue: we'll get every PropertyChanged event only with a property name. So we had to check every time, whether this property is our property using 'magic' string. Furthermore we always had to keep it in our heads, when we rename or refactor a property we also need to change those compare strings. So, might be working, but not a good idea. Something similar would be nice:

this.SubscribeOnPropertyChanged(() => this.Person, p => p.Name, OnNameChanged);

Ok, let's see how to achieve this. Create a new method in our ViewModelBase class. First a class selector (which is actually a property or field of our MainViewModel), then a property selector for the selected class, and an Action to execute in case of any changes. The trick is: we pick the class and store it in our external Action reference collection.

private readonly List<PropertySubscription> OnChangedActions = 
    new List<PropertySubscription>();
 
protected void SubscribeOnPropertyChanged<TClass, TProperty>(
    Expression<Func<TClass>> classSelector, 
    Expression<Func<TClass, TProperty>> propertySelector, Action onPropertyChanged)
   where TClass : ViewModelBase
{
   var propertyName = ExtractPropertyName(propertySelector.Body as MemberExpression);
   var targetClass = classSelector.Compile();

   targetClass().OnChangedActions.Add( 
       new PropertySubscription(propertyName, onPropertyChanged));
}

PropertySubscription is really just a metaclass to store external subscriptions. You can use a simply KeyValuePair<string, Action> instead. To avoid redundant code, ExtractPropertyName must be extracted into two methods. Simply create a new method with the same name and copy the last few lines from the original one into the new one:

private string ExtractPropertyName(MemberExpression me)
{
   if ((me != null) && !string.IsNullOrEmpty(me.Member.Name))
   {
      return me.Member.Name;
   }

   throw new ArgumentException("Property could not be found.");
}

Ok, so we store it, but it does not do anything. We need to execute those actions whenever a property change occurs. Create a method which filters our collection on property name and execute every subscription action. Don't forget to store actions into a local variable inside the iteration to avoid "Access to modified closure".

private void ExecuteExternalSubcriptions(string propertyName)
{
   var actions = this.OnChangedActions.Where(s => s.PropertyName == propertyName);

   foreach (var action in actions)
   {
      var local = action;
      if (local.OnChangedAction != null)
      {
         local.OnChangedAction();
      }
   }
}

There is only one step left, add this method to our RaisePropertyChanged method. The new one is something like:

private void RaisePropertyChanged(string propertyName)
{
   var handler = this.PropertyChanged;
   if (handler != null)
   {
      handler(this, new PropertyChangedEventArgs(propertyName));
   }

   this.ExecuteExternalSubcriptions(propertyName);
}

From now on, every time a property has been changed, we also check external subscriptions and if we found any, execute them after property changed event. Thanks to this little extension in the ViewModelBase we can easily execute custom actions outside our class without strong references. Since we reference in a (probably) short living class to a long living class GC can dispose our object or class without problem. Furthermore developing is also much better and easier, working with expressions does not let us to compile with typo and we can refactor or rename our properties without to worry about magic strings in our code.

I can't believe you are still reading :) To appreciate your patient I give you one more thing: subscriptions to any property change. As you can see, our previous method allows us to subscribe to one particular property change. But sometimes we need all of them. Subscribing to all of them would be silly, so let's just add one more method, without property selector.

private readonly object dummy = new object();
 
protected void SubscribeOnPropertyChanged<TClass>(
    Expression<Func<TClass>> classSelector, Action onPropertyChanged)
   where TClass : ViewModelBase
{
   this.SubscribeOnPropertyChanged(classSelector, x => x.dummy, onPropertyChanged);
}

But what is 'dummy and why? Like I said before, I really hate to build logic on strings, but to keep our code simply and effective we want to use the same collection. But our collection stores PropertySubscriptions, where property name is obligatory. Best way is to create a private field and use it as property in our subscription. What we need it filter out this property before we iterate through our actions. So, let's change our ExecuteExternalSubscriptions method:

private void ExecuteExternalSubscriptions(string propertyName)
{
   var actions = this.OnChangedActions.Where(
       s => s.PropertyName == propertyName || 
       s.PropertyName == this.ExtractPropertyName(() => this.dummy));

   foreach (var action in actions)
   {
      var local = action;
      if (local.OnChangedAction != null)
      {
         local.OnChangedAction();
      }
   }
}

And how it works? Here is a tiny code snippet:

public class MainWindowViewModel : ViewModelBase
{      
  private Person Person = new Person();

  public MainWindowViewModel()
  {
   // to subscribe on Person's name changes
   this.SubscribeOnPropertyChanged(() => this.Person, p => p.Name, OnNameChanged);

   // to subscribe on any property changes in Person clsas
   this.SubscribeOnPropertyChanged(() => this.Person, OnPersonChanged);
  }

  private void OnNameChanged()
  { }

  private void OnPersonChanged()
  { }
}



Monday, October 7, 2013

Event extension

To send notification from one class to an other Event is the best way. But to avoid exceptions we need to check it every time whether it is null or not. It isn't a big deal but a few extra lines every time you want to fire an event, and with every line you write in your code also incrase the possibility of a bug. So, why not an extension method?

public static class EventExtensions
{
   public static void RaiseEvent(this EventHandler handler, object sender, EventArgs e)
   {
      var local = handler;
      if (local != null)
      {
         local(sender, e);
      }
   }
}

Sooo easy. Store handler into a local variable to avoid "Access to modified closure" issue and simply fire an event, if it is not null. In practice it would be something like this:

public class SampleClass
{      
   private event EventHandler CustomEvent;

   public SampleClass()
   {
      this.CustomEvent.RaiseEvent(this, EventArgs.Empty);
   }
}

One simple line instead of five and any changes you might need to make in your application requires to change only one simple extension method. What do I mean? For example log every event.

Extend the INotifyPropertyChanged implemenation with a shorter setter

When a WPF application is needed, than probably a noticeable percentage of the code is property declaration, due MVVM, at least in the UI / client layer or in the contracts. Event with the method mentioned in one of my previous post the implementation costs 6-12 lines depends on how you break lines. After some testing I found a better way, a more elegant way to set a property value. However the LOC won't be less and the execution time will be increased it is also an option.
Stick to my old ViewModelBase class (if you don't know what I mean, you definitely have to read my previous post) let's extend it with a read only field to cache class Fields and initialize it in the constructor. It is Lazy because you don't necessary need it, only if the new SetAndRaisePropertyChanged is gonna be used.

private readonly Lazy<IEnumerable<FieldInfo>> Fields;

protected ViewModelBase()
{
  this.Fields = new Lazy<IEnumerable<FieldInfo>>(() => 
      this.GetType().GetFields(
          System.Reflection.BindingFlags.NonPublic | 
          System.Reflection.BindingFlags.Public | 
          System.Reflection.BindingFlags.Instance));
}

My goal was to define a method with only one parameter (the value). So, what I need is to figure out the property and the backing field. Since I use .NET4 [CallerMethodName] is not an option. But the StrackFrame and StrackTrace are always there.

private string ConvertPropertyNameToBackingField(string propertyName)
{
   return "_" + propertyName;
}

protected bool SetAndRaisePropertyChanged<TProperty>(TProperty value)
{
   var method = new StackFrame(1).GetMethod();
   if (method != null && method.Name.StartsWith("set_"))
   { 
      var propertyName = method.Name.Substring(4);
      var field = this.Fields.Value.SingleOrDefault(f => 
         f.Name == this.ConvertPropertyNameToBackingField(propertyName));

      if (field != null)
      {
         var oldValue = field.GetValue(this);
         var result = oldValue == null || oldValue.Equals(value) == false;

         if (result)
         {
            this.OnPropertyChangingHandler(propertyName, oldValue, value);

            field.SetValue(this, value);

            this.RaisePropertyChanged(propertyName);                  
         }

      return result;
      }

      throw new ArgumentException("Could not find backing field: "
          this.ConvertPropertyNameToBackingField(propertyName) + 
          " in class " + this.GetType().Name);
   }

   throw new InvalidOperationException(@"Simplified SetAndRaisePropertyChanged method 
     cannot be used outside of the property setter. In this case consider 
     to use the another overload with three parameters.");
}

And the usage?

private string _MyProperty;
public string MyProperty
{
   get { return _MyProperty; }
   set { this.SetAndRaisePropertyChanged(value); }
}

Peace of cake, isn't it? As you can see, it only works if you call it from the setter and there is some kind of naming convention.

And what are the numbers?

The very first setter calls in the ViewModel do not show a big differences. In case of 3 parameters it takes around 0.0015 seconds, while this one takes 0.002. Real differences are during 2nd, 3rd, 4th etc. call. With property selector, it only costs 0.00008, but this one needs around 0.0007, so factor ten. But if you really need performance you should consider to use the string version (without property selector).

Wednesday, October 2, 2013

How to implement INotifyPropertyChanging

I think anyone, who at least once developed a WPF application, has also met the INotifyPropertyChanged interface. It is the key to build a program based on MVVM pattern, it helps to refresh binding and keep UI and code behind sync. Just like its name says, you receive a notification after a property's value has changed. But what if you need a notification before it changes? Let's assume we want to track user's changes and rollback if it is needed. In this case the INotifyPropertyChanging interface has to be implemented. Unfortunately, however this interface exists in .NET, nothing supports it. It means, you don't get any update or notify during property changing. But it doesn't have to mean, that you can't implement it yourself. So, let's see:

First, INotifyPropertyChanged.

protected void RaisePropertyChanged(string propertyName)
{
  var handler = this.PropertyChanged;
  if (handler != null)
  {
    handler(this, new PropertyChangedEventArgs(propertyName));
  }
}

I don't really like to operate with 'magic' strings, furthermore you don't get any compile error, but runtime error in case of typo, which is quite irritating. So, make it private and create another one with property selector using Expression.

protected void RaisePropertyChanged<TProperty>(Expression<Func<TProperty>> propertySelector)
{
  var property = this.ExtractPropertyName(propertySelector);
  this.RaisePropertyChanged(property);
}
 
private string ExtractPropertyName<TProperty>(Expression<Func<TProperty>> propertySelector)
{
  MemberExpression me = propertySelector.Body as MemberExpression;
  if (me == null)
  {
    UnaryExpression ue = propertySelector.Body as UnaryExpression;
    if (ue != null)
    {
       me = ue.Operand as MemberExpression;
    }
  }

  if ((me != null) && !string.IsNullOrEmpty(me.Member.Name))
  {
    return me.Member.Name;
  }

  throw new ArgumentException("Property could not be found.");
}

Alright. So far so good. But it would be better, if we hadn't write in every property setter a value compare, a backing field setter and a raise. We can use a SetAndRaisePropertyChanged method instead. It has three parameters: a property selector expression, a backing field reference and the value itself. If the value really changed, we set it and raise a property change.

protected bool SetAndRaisePropertyChanged<TProperty>(
    Expression<Func<TProperty>> propertySelector, 
    ref TProperty backingField, TProperty value)
{
  var result = backingField == null || backingField.Equals(value) == false;

  if (result)
  {
    var propertyName = this.ExtractPropertyName(propertySelector);          
    backingField = value;          
    this.RaisePropertyChanged(propertyName);
  }

  return result;
}

In this moment, it wouldn't be necessary to explicitly extract the property name, but it make sense later. So, we have a base class, which provides a SetAndRaisePropertyChanged method. With this method you can implement a bindable property like this:

private string _myProperty;
public string MyProperty
{
   get { return _myProperty; }
   set { this.SetAndRaisePropertyChanged(() => this.MyProperty, ref _myProperty, value); }
}

Ok, after this little detour let's start to implement the INotifyPropertyChanging interface. You can add to your base class or not, it's up to you, has no effect after all. Our goal is, to receive a notification before a property actually changes. Create an empty generic virtual method, it can be overwritten in the inherited class to handle property changing. As the method signature shows, you get the property name, the old value and the new value as well.

protected virtual void OnPropertyChanging<TProperty>(
    string propertyName, TProperty oldValue, TProperty newValue)
{ }
  
You cannot cancel or prevent the change, at least not at this point. I assume the base class also implements the INotifyPropertyChanging interface and you have a PropertyChanging event, too. In this case:

private void OnPropertyChangingHandler<TProperty>( 
    string propertyName, TProperty oldValue, TProperty newValue)
{
   var hander = this.PropertyChanging;
   if (hander != null)
   {
      hander(this, new PropertyChangingEventArgs(propertyName));
   }

   // call virtual method after event
   this.OnPropertyChanging(propertyName, oldValue, newValue);
}

If not, you can simply remove the event handler part from the method. To make it work, add this handler method to the SetAndRaisePropertyChanged, right before backing field setter line. As result the new content of your method looks like this:

protected bool SetAndRaisePropertyChanged<TProperty>(
    Expression<Func<TProperty>> propertySelector, 
    ref TProperty backingField, TProperty value)
{
   var result = backingField == null || backingField.Equals(value) == false;

   if (result)
   {
      var propertyName = this.ExtractPropertyName(propertySelector);
      // call changing method
      this.OnPropertyChangingHandler(propertyName, backingField, value);
      backingField = value;
      this.RaisePropertyChanged(propertyName);
   }

   return result;
}

And that's it. All you need to do is inherit your class from this base class, use SetAndRaisePropertyChanged instead of explicitly comparing and setting value and overwrite OnPropertyChanging method. Like I mentioned before, you can't prevent value changes. The problem is that if property is bound to a visual element (e.g TextBox), the user already made changes, you receive any notification first in code behind after that. So, if you want to prevent it, you actually need to set it back to it's old value, but sometimes it is so late. Other issue can be a complex control, like a TabControl. If you try to prevent tab changes you might face with some inconsistency. The same page is visible, but an other tab header is selected.