Monthly Archives: August 2013

The WPF ListView

By default a ListView looks and acts much like a standard WPF ListBox (when in it’s default state) but ofcourse we can also include headers/columns and groupings whichon top of the basic list of data.

Let’s assume we’re wanting to display a collection of Person objects where the Person type is made up of FirstName, LastName and Age. For this example assume these are exposed by the People property on our view model.

To display our collection we can simply do the following

<ListView ItemsSource="{Binding People}" />

But this will display the type name for each item in our collection and ofcourse doesn’t have headings. So to add headings we need to use the following

<ListView ItemsSource="{Binding People}">
   <ListView.View>
      <GridView>
         <GridViewColumn Header="First Name" Width="150" 
                   DisplayMemberBinding="{Binding FirstName}"/>
         <GridViewColumn Header="Last Name" Width="150" 
                   DisplayMemberBinding="{Binding LastName}"/>
         <GridViewColumn Header="Age" Width="100" 
                   DisplayMemberBinding="{Binding Age}"/>
      </GridView>
   </ListView.View>
</ListView>

this will also display the members we’re binding to so no longer display the type name.

So far so good, but to add groupings we need to do a little more work. In XAML we have the following (in the Window ResourceDictionary)

<CollectionViewSource Source="{Binding People}" x:Key="GroupedItems">
   <CollectionViewSource.GroupDescriptions>
      <PropertyGroupDescription PropertyName="LastName" />
   </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

If using the above XAML we also need to alter the ListView’s ItemSource to this

<ListView ItemsSource="{Binding Source={StaticResource GroupedItems}}">

this will then bind to the GroupedItems. Note we must use the “Source=” XAML.

We can also easily declare the same groupings in C# code as per below

CollectionView collectionView = 
      (CollectionView)CollectionViewSource.GetDefaultView(list.ItemsSource);
PropertyGroupDescription pgd = new PropertyGroupDescription("LastName");
collectionView.GroupDescriptions.Add(pgd);

Note: in the above case our ListView has the x:Name=”list” and ofcourse doesn’t require the ItemsSource binding change listed for the XAML code.

Using the CollectionView we add property group descriptions but we need to amend our ListView XAML to use this. By adding the ListView.GroupStyle as per below, we create the control template for the groupings

<ListView.GroupStyle>
   <GroupStyle>
      <GroupStyle.ContainerStyle>
         <Style TargetType="GroupItem">
            <Setter Property="Template">
               <Setter.Value>
                  <ControlTemplate TargetType="{x:Type GroupItem}">
                     <StackPanel>
                        <TextBlock FontWeight="Bold" 
                                FontSize="14" Text="{Binding Path=Name}"/>
                        <ItemsPresenter/>
                     </StackPanel>
                  </ControlTemplate>
               </Setter.Value>
            </Setter>
         </Style>
      </GroupStyle.ContainerStyle>
   </GroupStyle>
</ListView.GroupStyle>

The key things to note in the above XAML are that we need to ensure we put the ItemsPresenter into the ControlTemplate or now items are displayed and we do not bind to the data but instead bind to the CollectionViewGroup which is what the CollectionViewSource groups the data into. So in this case Name represents the string data for the grouping name and we could also bind to ItemCount for example if we wanted to show to the user the number of items in the grouping.

Friend assemblies (or how to make internals visible to other assemblies)

As you know, the internal modifier denotes that types and type members are only accessible by code from the same assembly.

Therefore the DoSomething method in the following is not visible to other assemblies but can be using by code within the assembly which contains this type

public class MyClass
{
   internal int DoSomething()
   {
   }
}

In some cases it’s useful to have internal types or type members visible to other assemblies, but limited to only those assemblies. These assemblies are known as friend assemblies.

To denote the friend assemblies we add the InternalsVisibleTo attribute to the assembly who hosts the internals and specify the friend assembly in the following manner

[assembly: InternalsVisibleTo("FriendAssembly")]

Now the FriendAssembly can access the DoSomething method on type MyClass.

Dynamically resolve assemblies at runtime

I came across this recently. I must admit I’ve not personally had a need for it, but it’s an interesting “trick”, so I wrote a little reusable framework around it.

So let’s say you deploy an application without all of it’s dependencies as part of the expected dependency resolution path. For example, in this case I’ve embedded all the assemblies as resources into the EXE so I can deploy a single file, but the technique should allow us to also resolve the dependencies via some other technique, such as from a remote location.

Create an EXE application and add the DLL(s) or EXE(s) and optionally their PDB(s) to the application as embedded resources. As your application depends on one (or more) of these assemblies then one (or more) of them will also be referenced. Mark the referenced assemblies which you’ve embedded as Copy Local=false (obviously we’re not talking about the GAC assemblies here) so they’re not copied to the output folder, obvious if you run the application now it will fail to locate these required assembles as we’ve embedded them as resources.

So, when the application starts up it attempts to resolve any missing dependencies and if it has any problem resolving the dependencies it fires the AssemblyResolve event on the AppDomain.CurrentDomain, it’s at this point that we want to dynamically load the assemblies ourselves into the app domain.

What we need to do is attach an event handler to the AppDomain.CurrentDomain.AssemblyResolve, as per

AppDomain.CurrentDomain.AssemblyResolve +=
       DynamicAssemblyResolver.Resolve(args, new ResourceAssemblyResolver());

I now try to resolve the missing dependency using an IAssemblyResolver (in this instance that is the ResourceAssemblyResolver class).

Below is a helper class named DynamicAssemblyResolver which simple (potentially) loops through any supplied IAssemblyResolver implementations passing the AssemblyName that we’re trying to resolve

public class DynamicAssemblyResolver
{
   public static Assembly Resolve(ResolveEventArgs e, 
            IAssemblyResolver resolver, params IAssemblyResolver[] alternateResolvers)
   {
      return Resolve(e.Name, resolver, alternateResolvers);
   }

   public static Assembly Resolve(string nameToResolve, 
            IAssemblyResolver resolver, params IAssemblyResolver[] alternateResolvers)
   {
      return Resolve(new AssemblyName(nameToResolve), resolver, alternateResolvers);
   }

   public static Assembly Resolve(AssemblyName assemblyToResolve, 
            IAssemblyResolver resolver, params IAssemblyResolver[] alternateResolvers)
   {
      Assembly assembly = resolver.Resolve(assemblyToResolve.Name);
      if (assembly != null)
      {
         return assembly;
      }

      if (alternateResolvers != null)
      {
         foreach (IAssemblyResolver alternateResolver in alternateResolvers)
         {
            assembly = alternateResolver.Resolve(assemblyToResolve.Name);
            if (assembly != null)
            {
               return assembly;
            }
         }
      }
      return null;
   }
}

The interface for a resolver class looks like this

public interface IAssemblyResolver
{
   Assembly Resolve(string assemblyName);
}

and finally the implementation that resolves dependencies using the files embedded within the resource looks like

public class ResourceAssemblyResolver : IAssemblyResolver
{
   public Assembly Resolve(string assemblyName)
   {
      Assembly executingAssembly = Assembly.GetExecutingAssembly();
      return (from name in executingAssembly.GetManifestResourceNames() 
		where name.Contains(assemblyName) 
		select Resolve(executingAssembly, name)).FirstOrDefault();
   }

   private static Assembly Resolve(Assembly executingAssembly, string assemblyName)
   {
      try
      {
         using(Stream manifestResourceStream = 
                      executingAssembly.GetManifestResourceStream(assemblyName))
         {
            if (manifestResourceStream == null)
   	    {
               return null;
            }

            string pdb = Path.ChangeExtension(assemblyName, ".pdb");
	    using (Stream pdbResourceStream =                
                     executingAssembly.GetManifestResourceStream(pdb))
	    {
	       return Assembly.Load(Read(manifestResourceStream),
			(pdbResourceStream != null) ?
			Read(pdbResourceStream) : null, 								                
                        SecurityContextSource.CurrentAppDomain);
 	    }
         }
      }
      catch (Exception)
      {
         throw;
      }
   }

   private static byte[] Read(Stream stream)
   {
      byte[] array = new byte[stream.Length];
      stream.Read(array, 0, array.Length);
      return array;
   }
}

The above code tries to match the supplied assembly name with the resources found embedded in the calling assembly.

Note: A failing of the above approach is that if more than one file exists with the same name, i.e. MyLib.dll existing in multiple resources but in different folders (obviously), then the first one only is ever resolved.

A simple lookless control in WPF

One of the key design principles for designing controls in WPF is the separation of UI from the actual control implementation (or functionality if you prefer). The aim is to create a control with properties, methods, events, states etc. as needed that does not rely on the specifics of the way the UI displays the control.

I’m going to work through a very simple lookless control to just get an idea how such a control might be implemented.

What’s the control going to be ?

Okay I don’t want anything too large as this is mean’t as a quick and easy to follow post. So the control will be a countdown timer control. A control which takes a time, in seconds and each second decreases the count until it reaches zero at which point it stops.

The control will have the following properties

From – this will hold to countdown “from” value (in seconds). In other words the value we start the countdown at.
Current – this will hold the current value in the countdown, obviously this will reduce from the “From” value down to zero.
IsRunning – this will allow us to know if the countdown timer is running.

Steps

  1. Create a CountdownControl class and implement the properties described above
  2. Create a CountdownControl XAML file and create a default style
  3. Create an alternate UI by overriding the ControlTemplate

Let’s implement this thing

Step 1

So step 1 is to create a new class called CountdownControl, we will derive this from a Control as we’re not looking to extend any existing control for this. So it should look like

public class CountdownControl : Control
{
}

Nothing exciting there.

As we’re going to countdown from a given value and for this example we’ve assumed the use of seconds only. We’ll use the DispatcherTimer to give us an event every second which will allow us to decrement the current value accordingly. As this isn’t mean’t to be a step by step for coding this I’ll simply point out that we can use the snippets in Visual Studio 2012 (dp and dpp) to create the propeties as follows.

  1. Create the IsRunning as a dependency property with property changed event
  2. Create the CurrentProperty as a readonly dependency property
  3. Create the From as a dependency property with property changed event
  4. Create a CountdownControl constructor and add the code to created the timer
  5. create the timer tick event and have it decrement the Current property until it reaches 0 then set the IsRunning to false
  6. On the OnIsRunningRunningChanged either start or stop the timer depending on the value passed to it
  7. On the OnFromChanged, set the IsRunning to true if a value greater than 0 is assigned to the From property

And here’s the code

public class CountdownControl : Control
{
   private readonly DispatcherTimer timer;

   public CountdownControl()
   {
      timer = new DispatcherTimer();
      timer.Interval = TimeSpan.FromSeconds(1);
      timer.Tick += TimerTick;
   }

   private void TimerTick(object sender, EventArgs e)
   {
      if (Current > 0)
      {
         SetValue(CurrentPropertyKey, Current - 1);
         if (Current == 0)
         {
            IsRunning = false;
         }
      }
   }

   public static readonly DependencyProperty IsRunningProperty =
		DependencyProperty.Register("IsRunning", typeof(bool), 
                typeof(CountdownControl),
		new FrameworkPropertyMetadata((bool)false,
		new PropertyChangedCallback(OnIsRunningChanged)));

   public bool IsRunning
   {
      get { return (bool)GetValue(IsRunningProperty); }
      set { SetValue(IsRunningProperty, value); }
   }

   private static void OnIsRunningChanged(DependencyObject d, 
               DependencyPropertyChangedEventArgs e)
   {
      CountdownControl target = (CountdownControl)d;
      bool oldIsRunning = (bool)e.OldValue;
      bool newIsRunning = target.IsRunning;
      target.OnIsRunningChanged(oldIsRunning, newIsRunning);
   }

   protected virtual void OnIsRunningChanged(bool oldIsRunning, bool newIsRunning)
   {
      if (!DesignerProperties.GetIsInDesignMode(this))
      {
         if (newIsRunning)
            timer.Start();
         else
            timer.Stop();
      }
   }

   private static readonly DependencyPropertyKey CurrentPropertyKey
		= DependencyProperty.RegisterReadOnly("Current", typeof(int), 
                        typeof(CountdownControl),
			new FrameworkPropertyMetadata((int)0));

   public static readonly DependencyProperty CurrentProperty
		= CurrentPropertyKey.DependencyProperty;

   public int Current
   {
      get { return (int)GetValue(CurrentProperty); }
   }

   public static readonly DependencyProperty FromProperty =
		DependencyProperty.Register("From", typeof(int), typeof(CountdownControl),
		new FrameworkPropertyMetadata((int)0,
		new PropertyChangedCallback(OnFromChanged)));

   public int From
   {
      get { return (int)GetValue(FromProperty); }
      set { SetValue(FromProperty, value); }
   }

   private static void OnFromChanged(DependencyObject d, 
                 DependencyPropertyChangedEventArgs e)
   {
      CountdownControl target = (CountdownControl)d;
      int oldFrom = (int)e.OldValue;
      int newFrom = target.From;
      target.OnFromChanged(oldFrom, newFrom);
   }

   protected virtual void OnFromChanged(int oldFrom, int newFrom)
   {
      SetValue(CurrentPropertyKey, newFrom); 
      IsRunning = (newFrom > 0);
   }
}

As can be seen, there’s no UI code here, only properties and functionality yet this will implement a countdown clock.

Note: The user of the DesignerProperties.GetIsInDesignMode is to stop the control counting down when in the XAML designer

Before we move onto the next step, which is to add a default style/look, let’s finish up here by creating the following static constructor

static CountdownControl()
{
   DefaultStyleKeyProperty.OverrideMetadata(typeof(CountdownControl), 
		new FrameworkPropertyMetadata(typeof(CountdownControl)));
}

As per a previous post on extending an existing control, the DefaultStyleKeyProperty is here to change the metadata for this class to associate a new style with this specific type.

Step 2

Create a ResourceDictionary named CountdownControl.xaml and add the following code

<Style TargetType="{x:Type Controls:CountdownControl}">
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type Controls:CountdownControl}">
            <Grid>
               <TextBlock Text="{Binding Current, RelativeSource={RelativeSource TemplatedParent}}" />
            </Grid>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

There’s not masses to say here except that this will now display the Current property value as it counts down in a TextBlock. The use of the binding instead of TemplateBinding is covered in a previous post, but basically TemplateBinding is lightweight and does not support the type conversion from an int (the current property) to a string. So we have to use the more verbose Binding syntax to solve this.

Lastly, if you are creating this control in it’s own assembly and haven’t already got one, create a Themes folder in your project and add a Generic.xaml ResourceDictionary inside the folder. Then add the following XAML

<ResourceDictionary.MergedDictionaries>
   <ResourceDictionary Source="/SimpleControl;component/CountdownControl.xaml" />
</ResourceDictionary.MergedDictionaries>

Step 3

Now we can use the CountdownControl by simply adding the following

<Controls:CountdownControl From="30"/>

Note: This assumes you’ve a namespace for the CountdownControls aliased as Controls.

If you run the application now it should display a simple text countdown from 30 to zero.

So whilst our lookless code then got a default look, we now want to re-template it to something a little nicer (although still fairly simple).

We’re going to now re-template the control to use a progress bar to show the countdown. So let’s see the new Style for this.

<Style TargetType="{x:Type c:CountdownControl}">
   <Setter Property="Template">
      <Setter.Value>
          <ControlTemplate TargetType="{x:Type c:CountdownControl}">
             <Grid>
                <ProgressBar Minimum="0" Maximum="{Binding From, RelativeSource={RelativeSource TemplatedParent}}" 
                      Value="{Binding Current, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" Height="20"/>
             </Grid>
          </ControlTemplate>
       </Setter.Value>
    </Setter>
</Style>

As you can see we’re now also using the From property as well as the Current property. We might have also decided to use the IsRunning with a BooleanToVisibilityConverter to hide the progress bar when it reaches zero.

In Summary

We’ve created a control which began by having no UI and was lookless and also very much testable. We then created a basic default look so we could at least see something when designing with the control. Finally we created a nicer UI for our specific needs.