Saving the GridView column order in WPF

I’ll try to get to the tutorial later.

Here is the project file.

StoreColumnOrder.zip

How to find and remove unused references in a C# project

Often  your projects is created with default references, some of which you will never use. Sometime you add a reference but then end up not using it. Over time you may have over a dozen references in each of a dozen projects and you know you are not using half of them.

I know two tools that will resolve this. One if free and is a plugin only for this feature. The other is a commercial product and has hundred of features.

Remove Unused References – Free Tool

I prefer the free tool by far as it is a simple and easy to use Visual Studio plugin. So I will test it first.

Remove Unused References

Click the link and it download and installs in seconds.

Then you will see the feature when you right-click on a project in Visual Studio.

Click it and it will remove any references that are not actually being used.

Ok, now lets create a sample project and see if this will work.

I am created a new Console Application and added the following code to the Program.cs

using System;
using System.Data;

namespace TooManyReferences
{
    class Program
    {
        static void Main(string[] args)
        {
            // I need System, System.Data, and System.Xml
            DataTable table = new DataTable();
            table.Columns.Add(new DataColumn("FistName",typeof(String)));
            table.Columns.Add(new DataColumn("LastName", typeof(String)));
            DataRow row = table.NewRow();
            row["FirstName"] = "Jared";
            row["LastName"] = "Barneck";
            table.Rows.Add(row);
            Console.WriteLine(table.Rows[0]);
        }
    }
}

Now lets right-click on the project and choose Remove Unused References.

Unfortunately, my expectation were not met.

Expectatation

The following reference should remain:

  • System
  • System.Data
  • System.XML

My project should build.

Actual Result

The following references remained:

  • System.Data

My project failed to build with the following errors

Error 1 The type 'System.Xml.Serialization.IXmlSerializable' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. C:\Users\212070783\Documents\Visual Studio 2010\Projects\TooManyReferences\TooManyReferences\Program.cs 11 13 TooManyReferences
Error 2 The type 'System.ComponentModel.ISupportInitialize' is defined in an assembly that is not referenced. You must add a reference to assembly 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. C:\Users\212070783\Documents\Visual Studio 2010\Projects\TooManyReferences\TooManyReferences\Program.cs 11 13 TooManyReferences
Error 3 The type 'System.ComponentModel.ISupportInitializeNotification' is defined in an assembly that is not referenced. You must add a reference to assembly 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. C:\Users\212070783\Documents\Visual Studio 2010\Projects\TooManyReferences\TooManyReferences\Program.cs 11 13 TooManyReferences
Error 4 The type 'System.ComponentModel.IListSource' is defined in an assembly that is not referenced. You must add a reference to assembly 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. C:\Users\212070783\Documents\Visual Studio 2010\Projects\TooManyReferences\TooManyReferences\Program.cs 11 13 TooManyReferences
Error 5 The type 'System.ComponentModel.MarshalByValueComponent' is defined in an assembly that is not referenced. You must add a reference to assembly 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. C:\Users\212070783\Documents\Visual Studio 2010\Projects\TooManyReferences\TooManyReferences\Program.cs 11 13 TooManyReferences

Note: Remember TooManyReferences is the name of my sample project and that is actually confusing in the log.

Conclusion

This tool removes references it should not remove.

If you use this tool, try using it on one project at a time in a large solution, otherwise you could get overwhelmed with failures.

It is pretty easy to add back references, so it is usable, but if it could be taken one step further, to resolve the references needed by objects my code uses, then it would probably be the best and simplest tool out there for this.

Bug Submitted

Remove Unused References – Commerical Tool

Resharper is the commercial tool that solves this problem. Unfortunately it is not free. However, it works well and I don’t currently have a license, but remember that it did not remove needed references when I last used it. Here is a link for more information.

http://www.jetbrains.com/resharper/webhelp/Refactorings__Remove_Unused_References.html

Visual Studio Training Videos – A check list of videos from WindowsClient.net

WPF in Visual Studio Training Videos


Overview

WPF – Getting Started

WPF – Design, Layout, Styles, T

WPF – Advanced

3D, Animation, Video, Sound

All Videos


Sheet 1: WPF – Getting Started

WPF – Getting Started and more
Completed Introduction Videos
Your First WPF Application 08 min 33 sec Getting Started
How Do I: Create a Simple Data Entry Form in WPF 24 min 32 sec Getting Started
How Do I: Create a Splash Screen in WPF 14 min Getting Started
How Do I: Define and Use Namespaces in WPF 23 min 16 sec Getting Started
How to Create a WPF Application 10 min 19 sec Getting Started

Accessing Command Line Parameters 06 min 13 sec Code
Reflections in Visual Studio and Blend 14 min 11 sec Code
Control When Bound Data is Updated 19 min 33 sec Binding
How Do I: Build a ValueConverter to Format Bound Data in WPF 17 min 17 sec Binding
How Do I: Create and Use a Converter to Change DataTypes 19 min 23 sec Binding
How Do I: Use FallbackValue in WPF Binding 09 min 38 sec Binding
How Do I: Use TargetNullValue to Handle Nullable Types in WPF Binding 10 min 44 sec Binding
How Do I: Using StringFormat when Multibinding 11 min Binding
How Do I: Visually Indicate Binding Error Status 12 min 16 sec Binding

How to Use XAML in WPF 10 min 34 sec XAML
Create and Browse Loose XAML Files 08 min 20 sec XAML
Extend Control Functionality Using XAML Attached Properties 23 min 47 sec XAML
How Do I: Use Attached Properties to Store Extra Data in WPF 17 min 16 sec XAML
How Do I: Using Path Markup Language to Define a Path 21 min 9 sec XAML
Create User Controls in WPF 12 min 43 sec Controls
How Do I: Build an Asynchronous Progress Bar in WPF 24 min 48 sec Controls
How Do I: Create a Simple WPF DataGrid to Edit Tabular Data 31 min 3 sec Controls
How Do I: Create Lookup Combobox in WPF 23 min 43 sec Controls
How Do I: Display Data in a List in WPF 11 min 47 sec Controls
How Do I: Use the WebBrowser Control in WPF 21 min 25 sec Controls
How to Create a User Control in WPF 11 min 38 sec Controls
Introducing the WPF 4 Calendar Control 17 min 49 sec Controls
Using Alternating Rows in an ItemsControl 14 min 54 sec Controls
Working With Context Menus in WPF 13 min 5 sec Controls
Creating Navigation Applications in WPF 11 min 45 sec Navigation
Passing Data Between Pages In Navigation Based Applications 08 min 55 sec Navigation
Use the Page Functions to Retrieve Data and Pass it Back to a Previous Page 12 min 22 sec Navigation
WPF Navigation Application 11 min 33 sec Navigation
Deploying a Standard WPF Application Using ClickOnce and Visual Studio 16 min 47 sec Deploy
Host a WPF Control in a Win32 Application 19 min 59 sec Integration
How Do I: Use a WPF Control in a Windows Form using ElementHost 06 min 52 sec Integration
How Do I: WinForms WPF Integration 11 min Integration
Creating and Consuming Resource Dictionaries in WPF and Silverlight 13 min 9 sec Resource Dictionaries
How Do I: Use Resource Files for Localization both in XAML and Code 25 min 16 sec Localization

Sheet 2: WPF – Design, Layout, Styles, T

WPF – Design, Layout, Styles, Templates
Completed Introduction Videos
How to Layout a WPF Application 14 min 5 sec Design
Layout Techniques for Windows Forms Developers 20 min 19 sec Design
Create Gadget Style Windows in WPF 07 min 37 sec Design
Create WPF Master – Detail UI Using Data Sources Window Object DataSource 25 min 24 sec Design
Grid Control Design-Time Row and Column Manipulation Features 05 min 40 sec Design
How Do I: Add Design Time Data to a Control 13 min 48 sec Design
How Do I: Create a Master-Detail Data Entry Form in WPF 24 min 58 sec Design
How Do I: Detect Designmode in a Usercontrol 10 min 26 sec Design
Apply Styles in WPF 12 min 40 sec Style
How Do I: Change the Appearance of Grouped Data Using Styles 18 min 40 sec Style
How Do I: Customize the Appearance of a ListBox in WPF 16 min 16 sec Style
How Do I: Customize the Appearance of ListBox ListItems in WPF 15 min 2 sec Style
How Do I: Use ResourceDictionary Elements Exported from Expression Design 2 19 min 3 sec Style
How to Use Styles in WPF 10 min 22 sec Style
Introduction to Themes in WPF 15 min 14 sec Style
Override a Style for a Local Control’s Property Value in WPF 12 min 34 sec Style
Sharing Styles Among Heterogeneous Elements 21 min 31 sec Style
Skinning a WPF Application 21 min 31 sec Style
Style Inheritance using BasedOn in WPF 17 min 28 sec Style
How to Apply Control Templates in WPF 12 min 24 sec Templates
How to Use Data Templates in WPF 14 min 59 sec Templates
Use a Control Template to Define a Desired Look 16 min 34 sec Templates
How Do I: Use Windows 7 Text-to-Speech from .NET 4 and WPF 20 min 36 sec Text-to-speech

Sheet 3: WPF – Advanced

WPF – Advanced
Completed Introduction Videos
How Do I: Create a Custom Command in WPF 18 min 06 sec Commands
How Do I: Use Command Binding in WPF 24 min 18 sec Commands

Create Dependency Properties in WPF 21 min 23 sec Dependency Properties
How Do I: Build Data-driven WPF Application using the MVVM pattern 47 min 23 sec MVVM
How Do I: Use ASP.NET Membership Provider for WPF Authentication 25 min 04 sec ASP.NET
Complex Logic Using Triggers in WPF 13 min 36 sec Triggers
Implementing Data Triggers in WPF 10 min 25 sec Triggers
Implementing Property Triggers in WPF 13 min 2 sec Triggers
Interactivity Through Triggers in WPF Control Templates 15 min 26 sec Triggers
How Do I: Implement Windows 7 Taskbar Icon Overlays with WPF 4 13 min 21 sec Taskbar integration
How do I: Use Windows 7 Taskbar Progress Reporting from WPF 4 10 min 45 sec Taskbar integration
How Do I: Associate a Validation Rule with a Binding 16 min 53 sec Validation
How Do I: Control Item Activation By Data Validation? 24 min 43 sec Validation
How Do I: Create a Custom Binding Validator 20 min Validation
How Do I: Hook Up and Display Validation in WPF 22 min 20 sec Validation
How Do I: Setting and Clearing Validation Errors in code 14 min 18 sec Validation
Adding Annotations to Flow Documents 04 min 35 sec ??
How to Use Isolated Storage 10 min 38 sec ??
How Do I: Retrieve XML Data From the Server in an XBAP Application 12 min 36 sec Service
How to Consume a Data Service in WPF 13 min 6 sec Service

How Do I: Use CollectionViews to Sort and Filter Data 24 min 23 sec Sort/Filter

Sheet 4: 3D, Animation, Video, Sound

WPF – 3D, Animation, Video, Sound
Completed Introduction Videos
How Do I: Apply Textures to a 3D object 24 min 22 sec 3D
How Do I: Create Custom Pixel Shader Effects for WPF 28 min 41 sec 3D
How Do I: Get Started with 3D Elements in WPF 31 min 39 sec 3D
How Do I: Work with Lighting in WPF 3D 20 min 26 sec 3D

Basic Animation in WPF Using XAML 19 min 26 sec Animation
Build a Custom GridLength Animation 20 min 18 sec Animation
Confine Animation to a Path 12 min 43 sec Animation
How Do I: Animate an Effect in WPF? 17 min 52 sec Animation
How Do I: Create a Dynamic Storyboard in WPF 20 min 8 sec Animation
How Do I: Use PointAnimation to Animate a Path in WPF 14 min 22 sec Animation
Kerning XAML Animations in WPF 16 min 18 sec Animation
How Do I: Add Sound to a WPF Application 17 min 48 sec Sound
Responding to Events with SoundPlayerAction 15 min 37 sec Sound
How Do I: Custom Easing Functions in WPF 4 16 min 49 sec Easing
Introduction to Easing Functions in WPF 4 15 min 23 sec Easing
Ink Basics in WPF 09 min 53 sec ??
Use PathGeometries in WPF 20 min 32 sec ??
Building a Client Profile Deployment for photoSuru 09 min 53 sec ??
Control Video Playback in WPF 14 min 36 sec Video
How Do I: Paint with Video in WPF 16 min 58 sec Video
How Do I: Use Video in WPF Applications 15 min 12 sec Video
Windows 7 Sensor and Location API Part 2 – Accelerometer as a Joystick 21 min 38 sec Gaming

Sheet 5: All Videos

WPF – All Videos
Completed Complete list of videos
Create WPF Master – Detail UI Using Data Sources Window Object DataSource 25 min 24 sec Design
Layout Techniques for Windows Forms Developers 20 min 19 sec Design
Grid Control Design-Time Row and Column Manipulation Features 05 min 40 sec Design
Creating and Consuming Resource Dictionaries in WPF and Silverlight 13 min 9 sec Resource Dictionaries
How Do I: Build My First WPF Application 32 min 40 sec Getting Started
How Do I: Setting and Clearing Validation Errors in code 14 min 18 sec Validation
How Do I: Build Data-driven WPF Application using the MVVM pattern 47 min 23 sec MVVM
How Do I: Use TargetNullValue to Handle Nullable Types in WPF Binding 10 min 44 sec Binding
How Do I: Using StringFormat when Multibinding 11 min Binding
How Do I: Use FallbackValue in WPF Binding 09 min 38 sec Binding
Windows 7 Sensor and Location API Part 2 – Accelerometer as a Joystick 21 min 38 sec Gaming
How Do I: Implement Windows 7 Taskbar Icon Overlays with WPF 4 13 min 21 sec Taskbar integration
How Do I: Use Windows 7 Text-to-Speech from .NET 4 and WPF 20 min 36 sec Integration
How Do I: Change the Appearance of Grouped Data Using Styles 18 min 40 sec Style
How Do I: Apply Textures to a 3D object 24 min 22 sec 3D
How Do I: WinForms WPF Integration 11 min Integration
How Do I: Use Resource Files for Localization both in XAML and Code 25 min 16 sec Localization
How do I: Use Windows 7 Taskbar Progress Reporting from WPF 4 10 min 45 sec Taskbar integration
How Do I: Create Custom Pixel Shader Effects for WPF 28 min 41 sec 3D
How Do I: Work with Lighting in WPF 3D 20 min 26 sec 3D
How Do I: Get Started with 3D Elements in WPF 31 min 39 sec 3D
How Do I: Use ASP.NET Membership Provider for WPF Authentication 25 min 04 sec ASP.NET
How Do I: Use a WPF Control in a Windows Form using ElementHost 06 min 52 sec Integration
How Do I: Create a Custom Command in WPF 18 min 06 sec Commands
How Do I: Custom Easing Functions in WPF 4 16 min 49 sec Easing
Introduction to Easing Functions in WPF 4 15 min 23 sec Easing
Introducing the WPF 4 Calendar Control 17 min 49 sec Controls
How Do I: Use Command Binding in WPF 24 min 18 sec Commands
How Do I: Use CollectionViews to Sort and Filter Data 24 min 23 sec Sort/Filter
How Do I: Control Item Activation By Data Validation? 24 min 43 sec Validation
How Do I: Animate an Effect in WPF? 17 min 52 sec Animation
Building a Client Profile Deployment for photoSuru 09 min 53 sec ??
How Do I: Visually Indicate Binding Error Status 12 min 16 sec Binding
How Do I: Create a Custom Binding Validator 20 min Validation
How Do I: Associate a Validation Rule with a Binding 16 min 53 sec Validation
How Do I: Add Design Time Data to a Control 13 min 48 sec Design
How Do I: Detect Designmode in a Usercontrol 10 min 26 sec Design
Using Alternating Rows in an ItemsControl 14 min 54 sec Controls
Control When Bound Data is Updated 19 min 33 sec Binding
Working With Context Menus in WPF 13 min 5 sec Controls
How Do I: Use the WebBrowser Control in WPF 21 min 25 sec Controls
Adding Annotations to Flow Documents 04 min 35 sec ??
How Do I: Create a Splash Screen in WPF 14 min Getting Started
How Do I: Create a Simple WPF DataGrid to Edit Tabular Data 31 min 3 sec Controls
How Do I: Create a Master-Detail Data Entry Form in WPF 24 min 58 sec Design
How to Use Styles in WPF 10 min 22 sec Style
How to Create a User Control in WPF 11 min 38 sec Controls
How to Create a WPF Application 10 min 19 sec Getting Started
How to Apply Control Templates in WPF 12 min 24 sec Templates
How to Consume a Data Service in WPF 13 min 6 sec Service
How to Use Data Templates in WPF 14 min 59 sec Templates
How to Layout a WPF Application 14 min 5 sec Design
How to Use XAML in WPF 10 min 34 sec XAML
Control Video Playback in WPF 14 min 36 sec Video
Build a Custom GridLength Animation 20 min 18 sec Animation
How Do I: Create a Dynamic Storyboard in WPF 20 min 8 sec Animation
How Do I: Build an Asynchronous Progress Bar in WPF 24 min 48 sec Controls
How Do I: Use Video in WPF Applications 15 min 12 sec Video
How Do I: Paint with Video in WPF 16 min 58 sec Video
How Do I: Hook Up and Display Validation in WPF 22 min 20 sec Validation
How Do I: Create Lookup Combobox in WPF 23 min 43 sec Controls
Responding to Events with SoundPlayerAction 15 min 37 sec Sound
How Do I: Add Sound to a WPF Application 17 min 48 sec Sound
How Do I: Display Data in a List in WPF 11 min 47 sec Controls
How Do I: Create a Simple Data Entry Form in WPF 24 min 32 sec Getting Started
How Do I: Use ResourceDictionary Elements Exported from Expression Design 2 19 min 3 sec Style
Extend Control Functionality Using XAML Attached Properties 23 min 47 sec XAML
How Do I: Use Attached Properties to Store Extra Data in WPF 17 min 16 sec XAML
How Do I: Define and Use Namespaces in WPF 23 min 16 sec Getting Started
How Do I: Customize the Appearance of a ListBox in WPF 16 min 16 sec Style
How Do I: Customize the Appearance of ListBox ListItems in WPF 15 min 2 sec Style
How Do I: Create and Use a Converter to Change DataTypes 19 min 23 sec Binding
How Do I: Build a ValueConverter to Format Bound Data in WPF 17 min 17 sec Binding
How Do I: Use PointAnimation to Animate a Path in WPF 14 min 22 sec Animation
How Do I: Retrieve XML Data From the Server in an XBAP Application 12 min 36 sec Service
How Do I: Using Path Markup Language to Define a Path 21 min 9 sec XAML
Create Dependency Properties in WPF 21 min 23 sec Getting Started
Use PathGeometries in WPF 20 min 32 sec ??
Ink Basics in WPF 09 min 53 sec ??
Confine Animation to a Path 12 min 43 sec Animation
Skinning a WPF Application 21 min 31 sec Style
Use a Control Template to Define a Desired Look 16 min 34 sec Templates
Create User Controls in WPF 12 min 43 sec Controls
Sharing Styles Among Heterogeneous Elements 21 min 31 sec Style
Override a Style for a Local Control’s Property Value in WPF 12 min 34 sec Style
Host a WPF Control in a Win32 Application 19 min 59 sec Integration
Interactivity Through Triggers in WPF Control Templates 15 min 26 sec Triggers
Kerning XAML Animations in WPF 16 min 18 sec Animation
Implementing Data Triggers in WPF 10 min 25 sec Triggers
Complex Logic Using Triggers in WPF 13 min 36 sec Triggers
Basic Animation in WPF Using XAML 19 min 26 sec Animation
Introduction to Themes in WPF 15 min 14 sec Style
Implementing Property Triggers in WPF 13 min 2 sec Triggers
Style Inheritance using BasedOn in WPF 17 min 28 sec Style
Apply Styles in WPF 12 min 40 sec Style
Deploying a Standard WPF Application Using ClickOnce and Visual Studio 16 min 47 sec Deploy
Create and Browse Loose XAML Files 08 min 20 sec XAML
Use the Page Functions to Retrieve Data and Pass it Back to a Previous Page 12 min 22 sec Navigation
Passing Data Between Pages In Navigation Based Applications 08 min 55 sec Navigation
WPF Navigation Application 11 min 33 sec Navigation
Create Gadget Style Windows in WPF 07 min 37 sec Design
Accessing Command Line Parameters 06 min 13 sec Code
How to Use Isolated Storage 10 min 38 sec ??
Build a Standard WPF Application 08 min 25 sec Getting Started
Creating Navigation Applications in WPF 11 min 45 sec Navigation
Reflections in Visual Studio and Blend 14 min 11 sec Code

MVVM and Drag and Drop Command Binding with an Attached Behavior

Drag and drop works quite well already with some UIElements, such as TextBox. However, you may want to using MVVM and binding to bind a command for dragging and dropping to a UIElement that doesn’t support drag and drop, such as a Grid or other container.

This can easily be done using an Attached Behavior. You may know what an Attached Property is and you may be wondering, what is the difference between an Attached Behavior and an Attached Property. An Attached Behavior is a type of an Attached Property that involves certain events, often user interaction events such a drag and drop.

Creating an Attached Behavior for use in WPF

So what is the basic recipe for creating an Attached Behavior.

  1. Use a public static class
  2. Add a static Dependency Property and and an associated PropertyChangedCallBack method (after testing, these can be private)
  3. Add a public method that is a static setter and getter (after testing the getter can be private)
  4. Add any static helper methods (usually these could be private)
  5. Add any additional code that is needed.

Handling Drag and Drop in WPF

If you are going to handle Drag and Drop in WPF, you need to make yourself acquainted with a particular static object called DataFormats (System.Windows.DataFormats, as there exists one in the Forms namespace too).   This object is going to help you. Microsoft says that the DataFormats class provides a set of predefined data format names that can be used to identify data formats available in the clipboard or drag-and-drop operations.[1You should take a moment to read about this class if you are not familiar with it. IDataObject and DataObject (which implements IDataObject) are also important to know and you should read about those as well.

Determine which types of data your need to handle with Drag and Drop. For each data type you plan to handle, you should check if the drag and drop data is that type and if so, handle it. You have the option to handle this in the code behind or in the behavior.

Also, with UIElements in WPF, the drag events are separate from the drop events, so we really don’t need a DragBehavior or DragAndDropBehavior, instead we only need a DropBehavior.[2]  You should read about the drag and drop events and understand which one you need to add a behavior too. We are going to use the PreviewDrop event.

Writing a DropBehavior

Ok, now that we have gained the knowledge we need, lets write a DropBavior static class.

  1. Create a new class and call it DropBehavior.
  2. Make the class both public and static.
  3. Add a DependecyProperty called PreviewDropCommandProperty (Lines 13 – 26).
  4. Create the Setter and Getter functions. (Lines 28-57)
  5. Create the PropertyChangedCallBack method. (Lines 59-78)
using System.Windows.Input;
using System.Windows;

namespace MVVM
{
    /// <summary>
    /// This is an Attached Behavior and is intended for use with
    /// XAML objects to enable binding a drag and drop event to
    /// an ICommand.
    /// </summary>
    public static class DropBehavior
    {
        #region The dependecy Property
        /// <summary>
        /// The Dependency property. To allow for Binding, a dependency
        /// property must be used.
        /// </summary>
        private static readonly DependencyProperty PreviewDropCommandProperty =
                    DependencyProperty.RegisterAttached
                    (
                        "PreviewDropCommand",
                        typeof(ICommand),
                        typeof(DropBehavior),
                        new PropertyMetadata(PreviewDropCommandPropertyChangedCallBack)
                    );
        #endregion

        #region The getter and setter
        /// <summary>
        /// The setter. This sets the value of the PreviewDropCommandProperty
        /// Dependency Property. It is expected that you use this only in XAML
        ///
        /// This appears in XAML with the "Set" stripped off.
        /// XAML usage:
        ///
        /// <Grid mvvm:DropBehavior.PreviewDropCommand="{Binding DropCommand}" />
        ///
        /// </summary>
        /// <param name="inUIElement">A UIElement object. In XAML this is automatically passed
        /// in, so you don't have to enter anything in XAML.</param>
        /// <param name="inCommand">An object that implements ICommand.</param>
        public static void SetPreviewDropCommand(this UIElement inUIElement, ICommand inCommand)
        {
            inUIElement.SetValue(PreviewDropCommandProperty, inCommand);
        }

        /// <summary>
        /// Gets the PreviewDropCommand assigned to the PreviewDropCommandProperty
        /// DependencyProperty. As this is only needed by this class, it is private.
        /// </summary>
        /// <param name="inUIElement">A UIElement object.</param>
        /// <returns>An object that implements ICommand.</returns>
        private static ICommand GetPreviewDropCommand(UIElement inUIElement)
        {
            return (ICommand)inUIElement.GetValue(PreviewDropCommandProperty);
        }
        #endregion

        #region The PropertyChangedCallBack method
        /// <summary>
        /// The OnCommandChanged method. This event handles the initial binding and future
        /// binding changes to the bound ICommand
        /// </summary>
        /// <param name="inDependencyObject">A DependencyObject</param>
        /// <param name="inEventArgs">A DependencyPropertyChangedEventArgs object.</param>
        private static void PreviewDropCommandPropertyChangedCallBack(
            DependencyObject inDependencyObject, DependencyPropertyChangedEventArgs inEventArgs)
        {
            UIElement uiElement = inDependencyObject as UIElement;
            if (null == uiElement) return;

            uiElement.Drop += (sender, args) =>
            {
                GetPreviewDropCommand(uiElement).Execute(args.Data);
                args.Handled = true;
            };
        }
        #endregion
    }
}

Using the DropBehavior in XAML

Ok, now it is really easy to add this to a Grid or other UIElement that doesn’t already handle Drag and Drop. If you try to add this to a TextBlox, which already handles Drag and Drop, this even doesn’t fire.

Examples

You can add the DropBehavior to a UserControl

<UserControl x:Class="DropBehaviorExample.ExampleView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:MVVM="clr-namespace:MVVM"
             mc:Ignorable="d"
             d:DesignHeight="300"
             d:DesignWidth="400"
             AllowDrop="True"
             MVVM:DropBehavior.PreviewDropCommand="{Binding PreviewDropCommand}"
             >
    <Grid>
    </Grid>
</UserControl>

Or you can add the DropBehavior to a Grid.

<UserControl x:Class="DropBehaviorExample.ExampleView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:MVVM="clr-namespace:MVVM"
             mc:Ignorable="d"
             d:DesignHeight="300"
             d:DesignWidth="400"
             AllowDrop="True"
             >
    <Grid MVVM:DropBehavior.PreviewDropCommand="{Binding PreviewDropCommand}">
    </Grid>
</UserControl>

And of course, you can put it on any UIElement that doesn’t already handle drag and drop.

Implementing the ICommand in the ViewModel

The following code is all you need in your ViewModel to bind the PreviewDropCommand.

        #region The RelayCommand that implements ICommand
        public ICommand PreviewDropCommand
        {
            get { return _PreviewDropCommand ?? (_PreviewDropCommand = new RelayCommand(HandlePreviewDrop)); }
            set
            {
                _PreviewDropCommand = value;
                NotifyPropertyChanged("PreviewDropCommand");
            }
        } private ICommand _PreviewDropCommand;

        #endregion

        #region The method encapsulated in the relay command
        private void HandlePreviewDrop(object inObject)
        {
            IDataObject ido = inObject as IDataObject;
            if (null == ido) return;

            // Get all the possible format
            string[] formats = ido.GetFormats();

            // Do what you need here based on the format passed in.
            // You will probably have a few options and you need to
            // decide an order of preference.
        }
        #endregion

Hope this helps you. I know when I first rounded up this information online, it was hard to understand because of lack of preparation information, so I made sure to provide that, and also lack of comments, so I made sure to provide that.

ItemsControl vs ListBox vs ListView in WPF

I wanted to highlight some of the similarities and some of the differences of ListBox vs ItemsControl.

Similarites of ItemsControl, ListBox, and ListView

These two controls are similar in a few ways.

  • All three are lists
  • All three support binding ItemsSource to a list
  • All three are ItemsControl objects as ListBox and ListView are descendants

Differences between ItemsControl, ListBox, and ListView

Inheritence

ItemsControl

ItemsControl uses an ItemsPresenter to present its children.

System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control
System.Windows.Controls.ItemsControl

ListBox

A ListBox is an ItemsControl but an ItemsControl is not a list box. Notice a list box is a descendant of ItemsControl but has a Selector object, which is abstract, that it specifically derives from. Inheriting from Selector provides ListBox with selection events and selection features that are missing from ItemsControl. ListBox adds a SelectionMode Dependency Property that allows for selection types of Single, Multiple, or Extended, which are defined in a SelectionMode enum. It uses ListBoxItem as its default child.


System.Windows.Controls.ItemsControl
System.Windows.Controls.Primitives.Selector
System.Windows.Controls.ListBox

ListView

ListView inherits from ListBox, so it is everything a ListBox is plus it has a View Dependency Property and some functions supporting the View Dependency Property. It uses ListViewItem as its default child.


System.Windows.Controls.ItemsControl
System.Windows.Controls.Primitives.Selector
System.Windows.Controls.ListBox
System.Windows.Controls.ListView

Sizing and Scrolling

  • ItemsControl takes as much space as it needs for its child elements, which can cause it to be larger than the screen. Because its size is based on its child controls, ItemsControl does not resize when re-sizing the screen.
  • ListBox and ListView take up all the space available to them from the parent and no more. Because the size is based on the parent control size, ListBox and ListView resize with the screen.
  • ItemsControl does not have a ScrollBar.
  • ListBox has both a vertical and horizontal ScrollBar.
Note: I learned that if you want to have an ItemsControl, but you want to have the scrolling. Simply make a copy of the ListBox style and change its TargetType to ItemsControl and use that style.

Styles and Templates

Note: These default styles are obtained using Expresion Blend by right-clicking a Control and choosing Edit Template | Edit a copy.

ItemsControl Default Style

This style is short and simple.

<ResourceDictionary
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<Style x:Key="ItemsControlDefaultStyle" TargetType="{x:Type ItemsControl}">
		<Setter Property="Template">
			<Setter.Value>
				<ControlTemplate TargetType="{x:Type ItemsControl}">
					<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
						<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
					</Border>
				</ControlTemplate>
			</Setter.Value>
		</Setter>
	</Style>
	<!-- Resource dictionary entries should be defined here. -->
</ResourceDictionary>

ListBox and ListView Default Style

ListBox and ListView have the same default style, with the only exception being the the TargetType, which is of course ListBox or ListView repectively.

Both have all the elements ItemsControl has, but also there are more Setters as Setters exist for the ScrollViewer and for the Border. ListBox and ListView styles also include a ScrollViewer in the ControlTemplate between the Border and the ItemsPresenter. ListBox and ListView also have a ControlTemplate.Triggers section.

<ResourceDictionary
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<SolidColorBrush x:Key="ListBorder" Color="#828790"/>
	<Style x:Key="ListBoxDefaultStyle" TargetType="{x:Type ListBox}">
		<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
		<Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
		<Setter Property="BorderThickness" Value="1"/>
		<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
		<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
		<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
		<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
		<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
		<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
		<Setter Property="VerticalContentAlignment" Value="Center"/>
		<Setter Property="Template">
			<Setter.Value>
				<ControlTemplate TargetType="{x:Type ListBox}">
					<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
						<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
							<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
						</ScrollViewer>
					</Border>
					<ControlTemplate.Triggers>
						<Trigger Property="IsEnabled" Value="false">
							<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
						</Trigger>
						<Trigger Property="IsGrouping" Value="true">
							<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
						</Trigger>
					</ControlTemplate.Triggers>
				</ControlTemplate>
			</Setter.Value>
		</Setter>
	</Style>
	<!-- Resource dictionary entries should be defined here. -->
</ResourceDictionary>

Note: If you accidentally put ListBoxItems under ListView, the items are wrapped in a ListViewItem control which has its own margin, which will make the items move 5 pixels further to the right.

Choosing betweeen ItemsControl, ListBox, and ListView

Choosing an ItemsControl

It is pretty easy to choose between ItemsControl and either ListBox or ListView. If you do not want the ability to select a row or switch the View, use ItemsControl. Otherwise, use ListBox or ListView.

Choosing an ListBox

Also, if you need the select feature but you do not need to be able to switch the View, use ListBox.

Choosing an ListView

If you need to be able to switch the View, then choose ListView. It doesn’t matter if you need the ability to select or not.

How to display a splash screen for at specific minimum length of time in WPF

WPF supports the ability to make an image load immediately as a splash screen to give your application the appearance of loading faster. It doesn’t actually load faster, but seeing the splash screen is a “feel good” experience for the user.

Adding a basic splash screen

Adding  a Splash Screen to a WPF application is very easy, now.

  1. Right-click any image in the start-up project and choose Properties.
  2. Set the Build Action to SplashScreen.

Yes it is that easy. You are done.

The problem with the basic splash screen

We found that on some machines the splash screen is a “must have” because the application load time was greater than two seconds. In fact, it was so long that without the splash screen, the user thought the program didn’t start and clicked it again. So a splash screen was added the default way.

However, on newer and faster machines, the application load time was less than half a second. For these newer and faster devices, the splash screen loads and closes so quickly it is awkward.

It would actually be better to always have the splash screen show for a minimum of two seconds whether the machine is fast or slow.

Adding a splash screen that displays for a minimum amount of time

Step 1 – Add an image to use as a splash screen to your project

  1. Add an image to your Visual Studio project.
    Note 1: I put mine in an images folder and since I it is a “Hello World” example, I just grabbed the first picture from an internet search.
    Note 2: Use a .png file.
  2. In Visual Studio, right-click on the image and choose Properties.
  3. Make sure the image is set to Resource.
    Important! Do not set it to Splash Screen.

Step 2 – Take control of the window startup

  1. Open the App.xaml file.
    <Application x:Class="SimpleSplashExample.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 StartupUri="MainWindow.xaml">
        <Application.Resources>
    
        </Application.Resources>
    </Application>
    
  2. Remove the StartupUri tag seen below in line 4.
    <Application x:Class="SimpleSplashExample.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 >
        <Application.Resources>
    
        </Application.Resources>
    </Application>
    
  3. Open the App.xaml.cs.
    using System.Windows;
    
    namespace SimpleSplashExample
    {
        /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App : Application
        {
        }
    }
    
  4. Add a couple integers as member variables, one for the minimum time, 1.5 seconds, and one for the splash screen fade time, .5 seconds.
  5. Override the OnStartup method.
  6. Add a SplashScreen object using the image you added earlier and show it.
  7. Add a StopWatch object to monitor the time and start timing.
  8. Load the Window object that previously was being loaded by the StartupUri, but don’t show the window yet.
  9. Stop the StopWatch and then see how much time has elapsed.
  10. If the time is less than 1.5 seconds sleep the remaining time.
  11. Stop the SplashScreen.
  12. Now, show your window.
    Note: I added comments showing how to do this in five basic steps.

    using System;
    using System.Diagnostics;
    using System.Threading;
    using System.Windows;
    
    namespace SimpleSplashExample
    {
        /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App : Application
        {
            private const int MINIMUM_SPLASH_TIME = 1500; // Miliseconds
            private const int SPLASH_FADE_TIME = 500;     // Miliseconds
    
            protected override void OnStartup(StartupEventArgs e)
            {
                // Step 1 - Load the splash screen
                SplashScreen splash = new SplashScreen("Images/Globe-256.png");
                splash.Show(false, true);
    
                // Step 2 - Start a stop watch
                Stopwatch timer = new Stopwatch();
                timer.Start();
    
                // Step 3 - Load your windows but don't show it yet
                base.OnStartup(e);
                MainWindow main = new MainWindow();
    
                // Step 4 - Make sure that the splash screen lasts at least two seconds
                timer.Stop();
                int remainingTimeToShowSplash = MINIMUM_SPLASH_TIME - (int)timer.ElapsedMilliseconds;
                if (remainingTimeToShowSplash > 0)
                    Thread.Sleep(remainingTimeToShowSplash);
    
                // Step 5 - show the page
                splash.Close(TimeSpan.FromMilliseconds(SPLASH_FADE_TIME));
                main.Show();
            }
        }
    }
    

You now have a splash screen with a nice, consistent user experience whether you have fast or slow hardware.

How to disable a Button on TextBox ValidationErrors in WPF

Lets say  you want to create a submittable form in WPF. You want to make sure the form is filled out with valid values and you want the Submit button to be disabled until the form is filled out with valid values. Of course, the error text should display on error only.

See the picture on the right.

This is quite simple. Here is a sample project that demonstrates this: WpfTextBoxValidation.zip

Accomplishing this is done by using a few different tools available:

  • ValidationRules
  • Binding and MultiBinding
  • Triggers and MultiDataTriggers

So the code is so simple, I am going to skip the step by step instructions for time reasons. However, the code is pretty self documenting as the object names are obvious and the UI objects are obvious, at least when viewed in the Designer.

<Window x:Class="WpfTextBoxValidation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfTextBoxValidation"
        Title="MainWindow" Height="350" Width="525">
    <Grid Name="MainGrid" Margin="10">
        <Grid.Resources>
            <Style TargetType="TextBox">
                <Setter Property="MaxWidth" Value="200" />
            </Style>
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" MinWidth="200" />
            <ColumnDefinition Width="237*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="129*" />
        </Grid.RowDefinitions>

        <!-- Labels -->
        <TextBlock Name="labelFirstName" Text="FirstName" Margin="5" />
        <TextBlock Name="labelLastName" Text="LastName" Grid.Row="1" Margin="5" />
        <TextBlock Text="Age" Grid.Row="2" Margin="5" />
        <TextBlock Text="Phone" Grid.Row="3" Margin="5" />

        <!-- TextBlocks -->
        <TextBox Name="TextBoxFirstName"  Grid.Column="1" Margin="5">
            <TextBox.Text>
                <Binding Path="FirstName" UpdateSourceTrigger="PropertyChanged" >
                    <Binding.ValidationRules>
                        <local:TextBoxNotEmptyValidationRule x:Name="FirstNameValidation" ValidatesOnTargetUpdated="True"
                                                             Message="You must enter a first name."/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox Name="TextBoxLastName" Grid.Row="1" Grid.Column="1" Margin="5">
            <TextBox.Text>
                <Binding Path="LastName" UpdateSourceTrigger="PropertyChanged" >
                    <Binding.ValidationRules>
                        <local:TextBoxNotEmptyValidationRule x:Name="LastNameValidation" ValidatesOnTargetUpdated="True"
                                                             Message="You must enter a last name."/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox Name="TextBoxAge" Grid.Row="2" Grid.Column="1" Margin="5">
            <TextBox.Text>
                <Binding Path="Age" UpdateSourceTrigger="PropertyChanged" >
                    <Binding.ValidationRules>
                        <local:OverThirteenValidationRule x:Name="AgeValidation" ValidatesOnTargetUpdated="True"/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox Name="TextBoxPhone" Grid.Row="3" Grid.Column="1" Margin="5">
            <TextBox.Text>
                <Binding Path="Phone" UpdateSourceTrigger="PropertyChanged" >
                    <Binding.ValidationRules>
                        <local:TextBoxNotEmptyValidationRule x:Name="PhoneValidation" ValidatesOnTargetUpdated="True"
                                                             Message="You must enter a phone number."/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>

        <!-- Validation List -->
        <StackPanel Grid.Row="4" Grid.ColumnSpan="2" Margin="5">
            <StackPanel.Resources>
                <Style TargetType="TextBlock">
                    <Setter Property="Foreground" Value="Red" />
                </Style>
                <local:ErrorCollectionToVisibility x:Key="ToVisibility" />
            </StackPanel.Resources>
            <TextBlock Visibility="{Binding ElementName=TextBoxFirstName, Path=(Validation.Errors), Converter={StaticResource ToVisibility}}">
                <TextBlock.Text>
                    <MultiBinding StringFormat="{}{0} - {1}">
                        <Binding ElementName="labelFirstName" Path="Text"/>
                        <Binding ElementName="TextBoxFirstName" Path="(Validation.Errors)[0].ErrorContent"/>
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
            <TextBlock Visibility="{Binding ElementName=TextBoxLastName, Path=(Validation.Errors), Converter={StaticResource ToVisibility}}">>
                <TextBlock.Text>
                    <MultiBinding StringFormat="LastName - {0}">
                        <Binding ElementName="TextBoxLastName" Path="(Validation.Errors)[0].ErrorContent"/>
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
            <TextBlock Visibility="{Binding ElementName=TextBoxAge, Path=(Validation.Errors), Converter={StaticResource ToVisibility}}">>
                <TextBlock.Text>
                    <MultiBinding StringFormat="Age - {0}">
                        <Binding ElementName="TextBoxAge" Path="(Validation.Errors)[0].ErrorContent"/>
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
            <TextBlock Visibility="{Binding ElementName=TextBoxPhone, Path=(Validation.Errors), Converter={StaticResource ToVisibility}}">>
                <TextBlock.Text>
                    <MultiBinding StringFormat="Phone - {0}">
                        <Binding ElementName="TextBoxPhone" Path="(Validation.Errors)[0].ErrorContent"/>
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
            <!--Text="{Binding ElementName=DirectoryBox, Path=(Validation.Errors)[0].ErrorContent}"-->
        </StackPanel>
        <Button Content="Submit" Grid.Column="1" Grid.Row="5" Margin="5" Padding="10,3,10,3" HorizontalAlignment="Right"
                Name="buttonSubmit" VerticalAlignment="Top">
            <Button.Style>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="IsEnabled" Value="false" />
                    <Style.Triggers>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding ElementName=TextBoxFirstName, Path=(Validation.HasError)}" Value="false" />
                                <Condition Binding="{Binding ElementName=TextBoxLastName, Path=(Validation.HasError)}" Value="false" />
                                <Condition Binding="{Binding ElementName=TextBoxAge, Path=(Validation.HasError)}" Value="false" />
                                <Condition Binding="{Binding ElementName=TextBoxPhone, Path=(Validation.HasError)}" Value="false" />
                            </MultiDataTrigger.Conditions>
                            <Setter Property="IsEnabled" Value="true" />
                        </MultiDataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
    </Grid>
</Window>

Now, lets look at the supporting objects:

using System.Windows;

namespace WpfTextBoxValidation
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Person p = new Person();
            //PersonViewModel pvm = new PersonViewModel() { Person = p };
            MainGrid.DataContext = p;
        }
    }
}

In The above class, I add an instance of the Person object and make that the DataContext.

using System;

namespace WpfTextBoxValidation
{
    public class Person
    {
        public String FirstName { get; set; }
        public String LastName { get; set; }
        public String Age { get; set; }
        public String Phone { get; set; }
    }
}

The above class is a simple standard person object for examples.

using System;
using System.Windows.Controls;

namespace WpfTextBoxValidation
{
    public class OverThirteenValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            if (value != null)
            {
                int age = 0;
                try
                {
                    age = Convert.ToInt32(value);
                }
                catch
                {
                    return new ValidationResult(false, "You must be older than 13!");
                }

                if (age > 13)
                    return ValidationResult.ValidResult;

            }
            return new ValidationResult(false, "You must be older than 13!");
        }
    }
}

The above class is an example ValidationRule that requires the person be 13 or older.

using System;
using System.Windows.Controls;

namespace WpfTextBoxValidation
{
    public class TextBoxNotEmptyValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            string str = value as string;
            if (str != null)
            {
                if (str.Length > 0)
                    return ValidationResult.ValidResult;
            }
            return new ValidationResult(false, Message);
        }

        public String Message { get; set; }
    }
}

The above class is an example ValidationRule that makes sure a TextBox is not empty.

using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace WpfTextBoxValidation
{
    class ErrorCollectionToVisibility : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var collection = value as ReadOnlyCollection<ValidationError>;
            if (collection != null && collection.Count > 0)
                return Visibility.Visible;
            else
                return Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return new object();
        }
    }
}

In the above class, I am using a converter to change to Visibility.Visible if there are no errors or change to Visibility.Collapsed if there is one or more errors.

With this simple project you should be able to now have a form in WPF with ValidationRules and disable the submit button should there be an ValidationErrors.

How to load a ResourceDictionary at Design Time in WPF

I am including my ResourceDictionary files as Content files. Content files means they are not compiled or embedded, but they are loose files on disk.

One issue I need to solve was how to have the Design View in Expression Blend or Visual Studio.

It seems that Expression Blend has a partial solution but it doesn’t work in Visual Studio for me.

Steps for loading a ResourceDictionary from a loose file at design time

  1. Locate your .proj file for your WPF Project.
  2. Edit the .proj file with you favorite text editor.
    Note: I use Notepad++.
  3. Find the ResourceDictionary file that is included as content.
        <Content Include="Resources\en-US\Common.View.LocalizationResources.en-US.xaml">
          <Generator>MSBuild:Compile</Generator>
          <SubType>Designer</SubType>
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </Content>
    
  4. Change it to this:
        <Content Include="Resources\en-US\Common.View.LocalizationResources.en-US.xaml"
          Condition="'$(DesignTime)'=='true'
          OR ('$(SolutionPath)'!='' AND Exists('$(SolutionPath)')
          AND '$(BuildingInsideVisualStudio)'!='true'
          AND '$(BuildingInsideExpressionBlend)'!='true')">
          <Generator>MSBuild:Compile</Generator>
          <SubType>Designer</SubType>
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </Content>
    
  5. Save and close the file.

 

Loading multiple ResourceDictionary files at design time

Sometimes Expression Blend will prompt you when it can’t find a resource and it will do this for you. However, it does something interesting.

It adds a file called DesignTimeResources.xaml in the Properties folder as a Page (not as Content).

    <Page Include="Properties\DesignTimeResources.xaml" 
      Condition="'$(DesignTime)'=='true' 
      OR ('$(SolutionPath)'!='' 
      AND Exists('$(SolutionPath)') AND '$(BuildingInsideVisualStudio)'!='true' 
      AND '$(BuildingInsideExpressionBlend)'!='true')">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
      <ContainsDesignTimeResources>true</ContainsDesignTimeResources>
    </Page>

The file then looks as follows:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>        
        <ResourceDictionary Source="E:\Dev\LD\Trunk\install\Common\LANDesk.Install.Common\Resources\en-US\Common.LocalizationResources.en-US.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    <!-- Resource dictionary entries should be defined here. -->
</ResourceDictionary>

And then you can add more ResourceDictionaries without modifying the .proj file.

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="E:\Dev\LD\Trunk\install\SomeApp\Branding\StyleResources.xaml"/>
        <ResourceDictionary Source="E:\Dev\LD\Trunk\install\SomeApp\Branding\AlternateStyleResources.xaml"/>
        <ResourceDictionary Source="E:\Dev\LD\Trunk\install\SomeApp\Resources\en-US\en-US.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    <!-- Resource dictionary entries should be defined here. -->
</ResourceDictionary>

ResourceDictionary with Relative Paths

Of course relative paths are more desired than static paths, especially when using projects among multiple people and from source control.

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="..\Branding\StyleResources.xaml"/>
        <ResourceDictionary Source="..\Branding\AlternateStyleResources.xaml"/>
        <ResourceDictionary Source="..\Resources\en-US\en-US.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    <!-- Resource dictionary entries should be defined here. -->
</ResourceDictionary>

Resources:
http://www.tweened.org/en/2010/06/07/design-time-resources-dans-blend-4/

How to change language at run-time in WPF with loadable Resource Dictionaries and DynamicResource Binding

Update: I created a project for this. It also has a NuGet package. 
See https://github.com/rhyous/WPFSharp.Globalizer.

Dynamically changing the language of a WPF application at run-time or on-the-fly is possible and quite simple.

With this solution you do not have Resources.resx files, you do not have to have x:Uid on all your XAML tags. See the expectations this solution is following here: My WPF Localization and Language Expectations. Most of my expectations are met with this solution.

Here is the sample project code: How to load a DictionaryStyle.xaml file at run time?

  • How to: Use a ResourceDictionary to Manage Localizable String Resources
  • Example 1 – Dynamic Localization in WPF with Code-behind

    Step 1 – Create a new WPF Application project in Visual Studio

    1. In Visual Studio, go to File | New | Project.
    2. Select WPF Application.
    3. Provide a name for the project and make sure the path is correct.
    4. Click OK.

    Step 2 – Configure App.xaml.cs to support dynamic ResourceDictionary loading

    The App.xaml.cs is empty by default. We are going to add a few variables, a constructor, and add a few simple functions. This is a fairly small amount of code.

    1. Open App.xaml.cs.
    2. Add a static member variable for App called Instance, so it can be accesses from anywhere.
    3. Add a static member variable for App called Directory, so it can be accesses from anywhere.
    4. Add a LanguageChangedEvent.
    5. Add a private GetLocXAMLFilePath(string inFiveCharLang) method.
    6. Add a public SwitchLanguage(string inFiveCharLanguage) method.
    7. Add a private SetLanguageResourceDictionary(string inFile) method.
    8. Add code to the constructor to initialize these variables and to set the default language.Note: The code is well commented.
      using System;
      using System.Globalization;
      using System.IO;
      using System.Threading;
      using System.Windows;
      
      namespace WpfRuntimeLocalizationExample
      {
          /// <summary>
          /// Interaction logic for App.xaml
          /// </summary>
          public partial class App : Application
          {
              #region Member variables
              public static App Instance;
              public static String Directory;
              public event EventHandler LanguageChangedEvent;
              #endregion
      
              #region Constructor
              public App()
              {
                  // Initialize static variables
                  Instance = this;
                  Directory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
      
                  // Load the Localization Resource Dictionary based on OS language
                  SetLanguageResourceDictionary(GetLocXAMLFilePath(CultureInfo.CurrentCulture.Name));
              }
      
              #endregion
      
              #region Functions
              /// <summary>
              /// Dynamically load a Localization ResourceDictionary from a file
              /// </summary>
              public void SwitchLanguage(string inFiveCharLang)
              {
                  if (CultureInfo.CurrentCulture.Name.Equals(inFiveCharLang))
                      return;
      
                  var ci = new CultureInfo(inFiveCharLang);
                  Thread.CurrentThread.CurrentCulture = ci;
                  Thread.CurrentThread.CurrentUICulture = ci;
      
                  SetLanguageResourceDictionary(GetLocXAMLFilePath(inFiveCharLang));
                  if (null != LanguageChangedEvent)
                  {
                      LanguageChangedEvent(this, new EventArgs());
                  }
              }
      
              /// <summary>
              /// Returns the path to the ResourceDictionary file based on the language character string.
              /// </summary>
              /// <param name="inFiveCharLang"></param>
              /// <returns></returns>
              private string GetLocXAMLFilePath(string inFiveCharLang)
              {
                  string locXamlFile = "LocalizationDictionary." + inFiveCharLang + ".xaml";
                  return Path.Combine(Directory, inFiveCharLang, locXamlFile);
              }
      
              /// <summary>
              /// Sets or replaces the ResourceDictionary by dynamically loading
              /// a Localization ResourceDictionary from the file path passed in.
              /// </summary>
              /// <param name="inFile"></param>
              private void SetLanguageResourceDictionary(String inFile)
              {
                  if (File.Exists(inFile))
                  {
                      // Read in ResourceDictionary File
                      var languageDictionary = new ResourceDictionary();
                      languageDictionary.Source = new Uri(inFile);
      
                      // Remove any previous Localization dictionaries loaded
                      int langDictId = -1;
                      for (int i = 0; i < Resources.MergedDictionaries.Count; i++)
                      {
                          var md = Resources.MergedDictionaries[i];
                          // Make sure your Localization ResourceDictionarys have the ResourceDictionaryName
                          // key and that it is set to a value starting with "Loc-".
                          if (md.Contains("ResourceDictionaryName"))
                          {
                              if (md["ResourceDictionaryName"].ToString().StartsWith("Loc-"))
                              {
                                  langDictId = i;
                                  break;
                              }
                          }
                      }
                      if (langDictId == -1)
                      {
                          // Add in newly loaded Resource Dictionary
                          Resources.MergedDictionaries.Add(languageDictionary);
                      }
                      else
                      {
                          // Replace the current langage dictionary with the new one
                          Resources.MergedDictionaries[langDictId] = languageDictionary;
                      }
                  }
              }
              #endregion
          }
      }
      

    Step 3 – Create a basic WPF User Interface

    We need a little sample project to demonstrate the localization, so lets quickly make one.

      1. Create a basic interface.
        Note 1: You can make one yourself, or you can use the basic interface I used. Just copy and paste from below.
        Note 2: I have already added a menu for selecting the Language for you.
    <Window x:Class="WpfRuntimeLocalizationExample.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="WPF Run-time Localization Example"
            MinHeight="350" MinWidth="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="30" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="25" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="15" />
                <ColumnDefinition Width="*" MinWidth="100"/>
                <ColumnDefinition Width="*" MinWidth="200"/>
                <ColumnDefinition Width="15" />
            </Grid.ColumnDefinitions>
            <DockPanel Grid.ColumnSpan="4" >
                <Menu DockPanel.Dock="Top" >
                    <MenuItem Header="_File">
                        <MenuItem Header="E_xit" Click="MenuItem_Exit_Click" />
                    </MenuItem>
                    <MenuItem Name="menuItemLanguages" Header="_Languages">
                        <MenuItem Tag="en-US" Header="_English" Click="MenuItem_Style_Click" />
                        <MenuItem Tag="es-ES" Header="_Spanish" Click="MenuItem_Style_Click" />
                        <MenuItem Tag="he-IL" Header="_Hebrew" Click="MenuItem_Style_Click" />
                    </MenuItem>
                </Menu>
            </DockPanel>
            <Label Content="First Name" Name="labelFirstName" Grid.Row="2" FlowDirection="RightToLeft" Grid.Column="1" />
            <Label Content="Last Name" Name="labelLastName" Grid.Row="4" FlowDirection="RightToLeft" Grid.Column="1" />
            <Label Content="Age" Name="labelAge" Grid.Row="3" FlowDirection="RightToLeft" Grid.Column="1" />
            <TextBox Name="textBox1" Grid.Column="2" Grid.Row="2" />
            <TextBox Name="textBox2" Grid.Column="2" Grid.Row="3" />
            <TextBox Name="textBox3" Grid.Column="2" Grid.Row="4" />
            <Button Content="Clear" Grid.Column="2" Grid.Row="5" Height="23" HorizontalAlignment="Right" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
        </Grid>
    </Window>
    
    1. Also populate the MainWindow.xaml.cs file with the code-behind needed for the menu click events.
      using System;
      using System.Globalization;
      using System.Windows;
      using System.Windows.Controls;
      
      namespace WpfRuntimeLocalizationExample
      {
          /// <summary>
          /// Interaction logic for MainWindow.xaml
          /// </summary>
          public partial class MainWindow : Window
          {
              public MainWindow()
              {
                  InitializeComponent();
                  foreach (MenuItem item in menuItemLanguages.Items)
                  {
                      if (item.Tag.ToString().Equals(CultureInfo.CurrentUICulture.Name))
                          item.IsChecked = true;
                  }
              }
      
              private void MenuItem_Exit_Click(object sender, RoutedEventArgs e)
              {
                  Environment.Exit(0);
              }
      
              private void MenuItem_Style_Click(object sender, RoutedEventArgs e)
              {
                  // Uncheck each item
                  foreach (MenuItem item in menuItemLanguages.Items)
                  {
                      item.IsChecked = false;
                  }
      
                  MenuItem mi = sender as MenuItem;
                  mi.IsChecked = true;
                  App.Instance.SwitchLanguage(mi.Tag.ToString());
              }
      
              private void button1_Click(object sender, RoutedEventArgs e)
              {
                  labelFirstName.Content = labelLastName.Content = labelAge.Content = string.Empty;
              }
          }
      }
      

    Though localization is not yet working, this should compile and run.

    Step 4 – Create Resource Dictionaries for Localization

    By recommendation of my expert localization team, we are going to create a folder for each language, using the five character string (en-US, es-ES, he-IL), and put a ResourceDictionary in each folder. The resource dictionary will also have the five character language string.

    1. Create the folder and the file.
      1. Right-click on the project in Visual Studio and choose Add | New Folder.
      2. Name the folder en-US
      3. Right-click on the en-US folder and choose Properties.
      4. Set the ‘Namespace Provider’ value to false.
      5. Right-click on the en-US folder and choose Add | Resource Dictionary.
      6. Provide a file name and make sure that Resource Dictionary (WPF) is selected.
      7. Note: I named my first resource dictionary LocalizationDictionary.en-US.xaml.
      8. Click Add.
      9. Right-click on the LocalizationDictionary.en-US.xaml file and choose Properties.
      10. Set ‘Build Action’ to ‘Content’.
      11. Set ‘Copy to Output Directory’ to be ‘Copy if newer’.
      12. Set ‘Custom Tool’ to blank.
    2. Name the ResourceDictionary.
      1. Open the resource LocalizationDictionary.en-US.xaml
      2. Add a reference to the System namespace from the mscorlib assembly.
      3. Add a string with the x:Key set to ResourecDictionaryName.
      4. Set the string value to “Loc-en-US”.
        Important! Because our code is specifically looking for Loc-, you need to use that scheme or change the code.
      5. Add to the string a Localization.Comment and set the value to $Content(DoNotLocalize).
      6. Save the resource dictionary.
        <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                            xmlns:sys="clr-namespace:System;assembly=mscorlib">
        
            <!-- The name of this ResourceDictionary. Should not be localized. -->
            <sys:String x:Key="ResourceDictionaryName" Localization.Comments="$Content(DoNotLocalize)">Loc-en-US</sys:String>
        
        </ResourceDictionary>
        
    3. Repeat all the steps in steps 1 and 2 for each langauge.
      Note: We will do the following three languages in this example:

      1. en-US
      2. es-ES
      3. he-IL

    Step 4 – Localize the strings

    We now are going to find each string that needs to be localized, add a string resource in our localization resource dictionary, and replace the string with DynamicResource binding.
    1. Open the MainWindow.xaml.
    2. The first string is the Title of the Window.
      Note: My window title is “WPF Run-time Localization Example”
    3. Replace the value with a DynamicResource to MainWindow_Title.
      Here is a snippet…

      <Window x:Class="WpfRuntimeLocalizationExample.MainWindow"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              Title="{DynamicResource ResourceKey=MainWindow_Title}"
              MinHeight="350" MinWidth="525">
          <Grid>
      
    4. Open the LocalizationDictionary.en-US.xaml.
    5. Add a string as a resource for the MainWindow’s  Title, making sure the x:Key value is matches the ResourceKey in the MainWindow.xaml: MainWindow_Title.
          <!-- Localized strings -->
          <sys:String x:Key="MainWindow_Title">WPF Run-time Localization Example</sys:String>
      
    6. Repeat steps for each of the remaining string that needs to be localized.
      The following strings need to be localized in my sample UI:

      1.  _File
      2. E_xit
      3. _Language
      4. _English
      5. _Spanish
      6. _Hebrew
      7. First Name
      8. Last Name
      9. Age
      10. Clear
    You program should now compile and switch language.

    Step 5 – Configure the FlowDirection

    The main motivation for adding Hebrew to this example is so that we can show how to dynamically switch FlowDirection for languages that flow from right to left.

    Note: This step is optional and only necessary if your application will support a language that flows right to left.

    1. Add two FlowDirection resources to the LocalizationDictionary.en-US.xaml files.
          <!-- Localization specific styles -->
          <FlowDirection x:Key="FlowDirection_Default" Localization.Comments="$Content(DoNotLocalize)">LeftToRight</FlowDirection>
          <FlowDirection x:Key="FlowDirection_Reverse" Localization.Comments="$Content(DoNotLocalize)">RightToLeft</FlowDirection>
      
    2. For Spanish, copy these same lines to the LocalizationDictionary.es-ES.xaml file. Spanish and English have the same FlowDirection.
    3. For Hebrew, (you have probably already guessed this), add these same lines to the LocalizationDictionary.he-IL.xaml file but reverse the values.
          <!-- Localization specific styles -->
          <FlowDirection x:Key="FlowDirection_Default" Localization.Comments="$Content(DoNotLocalize)">RightToLeft</FlowDirection>
          <FlowDirection x:Key="FlowDirection_Reverse" Localization.Comments="$Content(DoNotLocalize)">LeftToRight</FlowDirection>
      
    4. Open the MainWindow.xaml file.
    5. Add a FlowDirection tag to the MainWindow.xaml file.
    6. Set the FlowDirection value to using DynamicResource binding to FlowDirection_Default.Here is the XAML snipppet.
      <Window x:Class="WpfRuntimeLocalizationExample.MainWindow"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              Title="{DynamicResource MainWindow_Title}"
              MinHeight="350" MinWidth="525"
              FlowDirection="{DynamicResource FlowDirection_Default}">
          <Grid>
      

    Build compile and test. Both the language and FlowDirection should now change when switching to Hebrew.

    See the Framework for this here:

    https://github.com/rhyous/WPFSharp.Globalizer

    Resources

    My WPF Localization and Language Expectations

    WPF Localization and Language switching at run-time is not exactly solved clearly by Microsoft.  After my experience (which includes researching for days on separate occasions and changing to localize using Resources.resx when localizing with BAML was not working for everyone involved) I had come to the conclusion that WPF Localization was just going to remain a black mark on WPF until Microsoft provided an easy recommended solution.

    Microsoft has a lot of information on localization.  They have pages and pages of it and a lot of talks about localization using Resources.resx or using BAML (Binary XAML).

    I came to realize that I had the following expectations:

    1. Development for Localization should be easy.
    2. Development for Localization should not require “extra” libraries or separate projects.
    3. Localized strings should come from the same place for XAML as for C# code.
    4. Language switching should be a run-time option.
    5. Localization changes should not require a rebuild or recompile.
    6. Localization method should allow for us of a localization tool (such as Alchemy Catalyst).
    7. Localization should not require every item has an a unique identifier (as in no x:Uid tags in WPF).
    8. Missing strings in any language should be easily identified.
    9. FlowDirection should change with language when appropriate (such as for Hebrew).

    Neither the Resources.resx or the XAML solutions seemed to meet my expectations.

    Time came to decide on a localization method for WPF again, and I again embarked into similar research as before. I found all the same answers.

    However, I am now a WPF Expert. A Senior WPF Developer if you can call anyone such for such a young technology.

    I went through all the same pages as before only this time, I pieced together a localization solution that comes the closest to meeting all my expectations.

    If you don’t agree with most of my expectations, feel free to use another WPF localization solution. I am not going to argue that mine is the best for everyone, just the best for me and my expectations.

    In all my searching I have found no one who is using my solution. Expect my new solution soon and link at the end of this post soon.

    How to change language at run-time in WPF with loadable Resource Dictionaries and DynamicResource Binding (Example 1)