Archive for the ‘C# (C-Sharp)’ Category.

Getting the line count of a wrapped TextBlock in WPF

OK, so TextBlock does have a LineCount property, the only problem is, it is a private Property. It seems like half the private and internal fields should be public or at least protected so the children can get at them.

Rant: Sometimes I shake my head at the decisions made by the original developers, then I remember WPF is awesome and these little implementation mistakes aren’t always a big deal. Still, if they would just open source WPF, we could submit such a fix in seconds.

Well, let’s get around this. Did you know that you can access private fields and properties using reflection? You can. Simply follow the steps in this post:

How to get and set private fields or properties in C#

We can use reflection to get the LineCount value. In the article, they use a PrivateValueAccessor static class. However, for this purpose, I will simply take the needed method.

Here is a child class of TextBlock that gets LineCount. It also updates the LineCount on Loaded and on SizeChanged, as the LineCount is zero before the control is loaded. Once it is loaded a resize could change the line count.

using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Rhyous.TextBlock.Controls
{
    public class TextBlock2 : System.Windows.Controls.TextBlock, INotifyPropertyChanged
    {
        public const string LineCountPropertyName = "LineCount";

        public TextBlock2()
        {
            Loaded += OnLoaded;
            SizeChanged += TextBlock2_SizeChanged;
        }

        public int LineCount
        {
            get { return (int)GetPrivatePropertyInfo(typeof(System.Windows.Controls.TextBlock), LineCountPropertyName).GetValue(this); }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                PropertyChanged(this, e);
            }
        }

        private void TextBlock2_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            NotifyPropertyChanged(LineCountPropertyName);
        }

        private void OnLoaded(object sender, System.Windows.RoutedEventArgs e)
        {
            NotifyPropertyChanged(LineCountPropertyName);
        }

        private BindingFlags Flags = BindingFlags.Instance
                                   | BindingFlags.GetProperty
                                   | BindingFlags.NonPublic;

        private PropertyInfo GetPrivatePropertyInfo(Type type, string propertyName)
        {
            var props = type.GetProperties(Flags);
            return props.FirstOrDefault(propInfo => propInfo.Name == propertyName);
        }
    }
}

Here is an example where I use it. I added to additional controls, so you can see that the LineCount is 0 before render and 5 after render.

    <controls:TextBlock2 x:Name="Tb2" TextWrapping="Wrap" MaxWidth="100" HorizontalAlignment="Left"
                         Text="Some very long text that absolutely must demonstrate wrapping." />
    <TextBlock Name="BeforeRender2" Text="{Binding LineCount, ElementName=Tb2, StringFormat='TextBox2 Line Count before render: {0}', Mode=OneTime}"/>
    <TextBlock Name="AfterRender2"  Text="{Binding LineCount, ElementName=Tb2, StringFormat='TextBox2 Line Count after render: {0}'}" />

Binding to ICommand with Xamarin Forms

Alternate title

Why a Xamarin forms Button bound to ICommand doesn’t enable or disable automtically via CanExecute

So I’ve been pretty excited about Xamarin Forms being implemented with Xaml. I recently decided to take time to implement binding using MVVM and just see how it works.

I used to use a common object called RelayCommand that implemented the ICommand interface. However, there is no need for this object in Xamarin Forms, because Xamarin Forms has Command and Command<T> that both implement this.

So in WPF, I have an example for ICommand. It used both

<UserControl x:Class="RelayCommandExample.View.HelloWorldView"
             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" 
             mc:Ignorable="d"
             d:DesignHeight="200"
             d:DesignWidth="300"
             >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Label Grid.Row="0">
            <TextBlock Text="{Binding Text}" />
        </Label>
        <Button Grid.Row="1" Content="{Binding Button1.Text}" Command="{Binding Button1.Command}"/>
    </Grid>
</UserControl>

I have some simple view model properties that this view binds to.

	public String Text
	{
		get { return _Text; }
		set { SetProperty(ref _Text, value); }
	} private string _Text;

	public ButtonViewModel Button1
	{
		get
		{
			return _Button1 ?? (_Button1 = new ButtonViewModel
			{
				Text = "Click me!",
				Command = new RelayCommand(f => Button1Clicked(), f => Button1CanClick())
			});
		}
	} private ButtonViewModel _Button1;        

	private void Button1Clicked()
	{
		Text = "Button clicked " + ++_ClickCount + " times.";
	} private int _ClickCount;

	private bool Button1CanClick()
	{
		return _ClickCount < 10;
	}

I also used a ButtonViewModel in the above code. Note: My ButtonViewModel is far more advanced than this, but for this example, it has been stripped down to only the Button.Text and Button.Command.

    public class ButtonViewModel : ViewModelBase
    {
        public string Text
        {
            get { return _Text; }
            set { SetProperty(ref _Text, value); }
        } private string _Text;

        public RelayCommand Command
        {
            get { return _Command; }
            set { SetProperty(ref _Command, value); }
        } RelayCommand _Command;
    }

As you see, Button1CanClick() returns true for the first ten clicks, then returns false. That means the button should be enabled to start, but it should automatically disable after the tenth click. This works perfectly in WPF.

However, when I ported this code over to Xamarin Forms, I had a few problems.

CommandManager.RequerySuggested missing

The project didn’t build because RelayCommand references CommandManager.RequerySuggested which doesn’t work because it is part of PresentationCore, a library which doesn’t exist in Xamarin Forms.
Resolution: I replaced RelayCommand with Command from Xamarin Forms.

    public ButtonViewModel Button1
    {
        get
        {
            return _Button1 ?? (_Button1 = new ButtonViewModel
            {
                Text = "Click me!",
                Command = new Command(f => Button1Clicked(), f => Button1CanClick())
            });
        }
    } private ButtonViewModel _Button1;
    public class ButtonViewModel : ViewModelBase
    {
        public string Text
        {
            get { return _Text; }
            set { SetProperty(ref _Text, value); }
        } private string _Text;

        public Command Command
        {
            get { return _Command; }
            set { SetProperty(ref _Command, value); }
        } Command _Command;
    }

The project built perfectly and ran after that.

CanExecute method is not called after each click

The button didn’t disabled after 10 clicks. In fact, the CanExecute method was only called once at first load. I expected it to be called by any number of events, but it was never called. In WPF, it is CommandManager.RequerySuggested that makes this work, so with that code not existing, the CanExecuteChanged event must be fired manually.

Well, it seems that a simple way to do this would be to subscribe to the PropertyChanged event. So I deviced to bring back RelayCommand only this time inherit from Command.

using System;
using System.ComponentModel;
using Xamarin.Forms;

namespace MVVM
{
    public class RelayCommand : Command
    {
        public RelayCommand(Action<object> execute)
            : base(execute)
        {
        }

        public RelayCommand(Action execute)
            : this(o => execute())
        {
        }

        public RelayCommand(Action<object> execute, Func<object, bool> canExecute, INotifyPropertyChanged npc = null)
            : base(execute, canExecute)
        {
            if (npc != null)
                npc.PropertyChanged += delegate { ChangeCanExecute(); };
        }

        public RelayCommand(Action execute, Func<bool> canExecute, INotifyPropertyChanged npc = null)
            : this(o => execute(), o => canExecute(), npc)
        {
        }
    }
}

Now I can go back to using RelayCommand only add a parameter to pass the host object, using the keyword this.

    public ButtonViewModel Button1
    {
        get
        {
            return _Button1 ?? (_Button1 = new ButtonViewModel
            {
                Text = "Click me!",
                Command = new Command(f => Button1Clicked(), f => Button1CanClick(), this)
            });
        }
    } private ButtonViewModel _Button1;

So every time the PropertyChanged event fires, CanExecute is called. Note that for production, you may have to do checks outside of when the PropertyChanged event fires depending on what you are evaluating in CanExecute.

Button disabled by CanExecute

It works in Android and iOS as well.

Xamarin Forms Conclusion

I have no complaints with the technology. XAML and Binding and MVVM appear to be working quite well. All the benefits declarative UI and MVVM layers, combined with the ability to code for all mobile platforms in one place, in one language. It would be too hard to create full desktop app in WPF either as the ViewModel is reuseable. Xamarin also supports Mac OSX. So really you are looking at the future go to tool for building cross platform applications that aren’t web-based.

Using Aspect Oriented Programming to implement INotifyPropertyChanged as an attribute

Using Aspect Oriented Programming, specifically PostSharp, they have implemented INotifyPropertyChanged in two ways:

  1. A simple single INotifyPropertyChanged aspect as described here: http://www.sharpcrafters.com/solutions/notifypropertychanged
  2. The Definitive INotifyPropertyChanged which can be found here: http://www.sharpcrafters.com/blog/category/Toolkits.aspx

I recommend you look at both of those methods and see if they meet your needs. Of they do use them.

I didn’t find either implementation to my liking. The first is too simple, and the second is too complex. Both seem to think that I am going to want all my properties to kick off the OnPropertyChanged event. They both implement the class as follows.

[NotifyPropertyChanged]
public class Person
{
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }
}

All three properties will implement INotifyPropertyChanged even though it may be that Id never changes or if it does change, there is no need to notify anything.

NotifyPropertyChanged Attribute Expectations

Here is how I want to use Aspect Oriented Programming in my MVVM objects.

// This adds the interface and the OnNotifyPropertyChanged method.
[NotifyPropertyChangedClass]
public class Person
{
    // Does NOT call OnNotifyPropertyChanged
    public int Id { get; set; }

    // Calls OnNotifyPropertyChanged
    [NotifyPropertyChanged]
    public string FirstName { get; set; }

    // Calls OnNotifyPropertyChanged
    [NotifyPropertyChanged]
    public string LastName { get; set; }
}

Now, I also want to be able to specify the notifying of a property changed:

[NotifyPropertyChangedClass]
public class Person
{
    // Does NOT call OnNotifyPropertyChanged
    public int Id { get; set; }

    // Calls OnNotifyPropertyChanged for the property and the string params passed in.
    [NotifyPropertyChanged("LastCommaFirst", "FirstLast")]
    public string FirstName { get; set; }

    // Calls OnNotifyPropertyChanged
    [NotifyPropertyChanged]
    public string LastName { get; set; }

    public string LastCommaFirst
    {
        get { return string.Format("{1}, {0}", FirstName, LastName); }
    }

    public string FirstLast
    {
        get { return string.Format("{1}, {0}", FirstName, LastName); }
    }
}

Aspect MVVM

I was able to implement this with three very simple files: 1 interface, and two aspects. Here is how I implemented this:

The first file, INotifyPropertyChangedWithMethod.cs, is an interface that inherits from INotifyPropertyChanged. I used this to get access to the OnPropertyChanged event method.

using System.ComponentModel;

namespace MVVM
{
    public interface INotifyPropertyChangedWithMethod : INotifyPropertyChanged
    {
        void OnPropertyChanged(string propertyName);
    }
}

The second object is basically the same as the simple single INotifyPropertyChanged aspect, except it only implements the interface and does nothing to the setters.

using System;
using System.ComponentModel;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Extensibility;
using PostSharp.Reflection;

namespace MVVM
{
    [Serializable]
    [IntroduceInterface(typeof(INotifyPropertyChangedWithMethod), OverrideAction = InterfaceOverrideAction.Ignore)]
    [MulticastAttributeUsage(MulticastTargets.Class, Inheritance = MulticastInheritance.Strict)]
    public sealed class NotifyPropertyChangedClassAttribute : InstanceLevelAspect, INotifyPropertyChangedWithMethod
    {

        [ImportMember("OnPropertyChanged", IsRequired = false, Order = ImportMemberOrder.AfterIntroductions)]
        public Action OnPropertyChangedMethod;

        [IntroduceMember(Visibility = Visibility.Family, IsVirtual = true, OverrideAction = MemberOverrideAction.Ignore)]
        public void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                PropertyChanged(Instance, new PropertyChangedEventArgs(propertyName));
            }
        }

        [IntroduceMember(OverrideAction = MemberOverrideAction.Ignore)]
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

The final aspect is one that I use on the properties.

using System;
using PostSharp.Aspects;

namespace MVVM
{
    [Serializable]
    public class NotifyPropertyChanged : LocationInterceptionAspect
    {
        public NotifyPropertyChanged()
            : this(true, null)
        {
        }

        public NotifyPropertyChanged(params string[] inProperty)
            : this(true, inProperty)
        {
        }

        public NotifyPropertyChanged(bool inNotifyCurrentProperty, params string[] inProperty)
        {
            _NotifyCurrentProperty = inNotifyCurrentProperty;
            _OtherProperties = inProperty;
        }

        private readonly string[] _OtherProperties;
        private readonly bool _NotifyCurrentProperty;

        public override void OnSetValue(LocationInterceptionArgs args)
        {
            // Do nothing if the property value doesn't change
            if (args.Value == args.GetCurrentValue())
                return;

            args.ProceedSetValue();

            var npc = args.Instance as INotifyPropertyChangedWithMethod;
            if (npc != null)
            {

                // Notify for current property
                if (_NotifyCurrentProperty)
                    npc.OnPropertyChanged(args.Location.PropertyInfo.Name);

                // Notify for other properties
                if (_OtherProperties != null)
                {
                    foreach (string otherProperty in _OtherProperties)
                    {
                        npc.OnPropertyChanged(otherProperty);
                    }
                }
            }
        }
    }
}

My MVVM objects still include RelayCommand, but they no longer need ObservableObject or ViewModelBase.

Differences Encountered using Aspect MVVM

Calling OnPropertyChanged or Adding to the PropertyChanged event

First, since the classes themselves don’t actually have code for INotifyPropertyChanged or the OnPropertyChanged method, what do you do if you need to actually call OnPropertyChanged in one of the classes methods instead of in a property? What if you need to add an method to the PropertyChanged event? Visual Studio is going to give compile errors? Both are easily doable using the interface.

private void SomeMethod(object sender)
{
    var npc = this as INotifyPropertyChangedWithMethod;
    if (npc != null)
        npc.OnPropertyChanged("Sentences");
}

 

private void Instance_SearchWordsChangedEvent(object sender)
{
    var npc = MyObject as INotifyPropertyChangedWithMethod;
    if (npc != null)
        npc.PropertyChanged += NpcOnPropertyChanged;
}

private void NpcOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
    // code here...
}

Download

Here is a sample project and a project template and also a separate AspectMVVM project if you want the code. I’ll open source it on CodePlex.com soon.

AspectMVVM Example Project.zip
AspectMVVM Project Template.zip
AspectMVVM.zip

An actual in-production MVVM architecture

Actual MVVM Design

So the last project where I implemented MVVM that is in production for an enterprise product, the design pattern actually grew to included more than just the three items: Model, View, ViewModel.

Instead it looked like the image you see to the right.

The arrows indicate access.

  • Controller – Has access to all other objects. Basically the controller is created and it loads the first Views and ViewModels and assigns the DataContext of the Views.
  • View –  The view is only consumed by the controller (and dynamically so the controller doesn’t actually reference the View project or dll). Since the view is completely independent it can be replaced any time. The View is only connected to the ViewModel through binding when the controller assigns a ViewModel to the DataContext of a View.
  • ViewModel – An adapter layer on top of the model and business that also implements the necessary objects that are expected in the View’s bindings. The ViewModel communicates with the controller in order to tell it to change screens/switch to a new view. It is important in this design to note that the ViewModel never references the View and is completely independent of the View, which allows it to be applied to any View.
  • Business – The code that actual does the work. It only needs access to the Model but both the Controller and ViewModel have access to use it. However, the Controller seldom uses it but the ViewModel heavily uses it.
  • Model – Data objects. It doesn’t know about anything else, but the Controller, Business, and ViewModel all know about the Model.

How this design formed

Originally the MVVM pattern was used and the project started as a single project, with a separate folder and namespace for Model-View-ViewModel times.

As the application progressed, this design was created as separation of concerns were applied to each layer and as items were broken out into separate projects/dlls.

Why the Controller became a separate layer

Initially it seems that the View or the ViewModel (either) could handle being the Controller. However, we found that neither the View or the ViewModel acting as the Controller was a good idea for a couple of reasons. First, if the View or the ViewModel were also the Controller then they became dependent on too many items. It became clear quickly that the ViewModel was a better choice of the two and so it was chosen at first. However, with references to the View available to the ViewModel, developers began to cheat and couple the View to the ViewModel, until the ViewModel could not build without that exact View and the View was supposed to be dynamic and interchangeable.

So to keep the View decoupled from the ViewModel and visa-versa, a separate Controller project was created and no reference between the View or ViewModel was allowed.

Note: Actually the Business and Controller layers are in the same dll.

Why the Business layer was separated from the ViewModel

Initially the Business layer and the ViewModel layer were the same layer. Some of the business existed directly in the ViewModel and some were in separate classes. It quickly became apparent that the ViewModels were 1) getting too large, and 2) breaking the single responsibility principle. It became apparent that in order to maintain small class files and the single responsibility principle that the Business needed to exist outside of the ViewModel and the ViewModel would simply call the a single Business object or method when needed.

Other mistakes

Initially the Controller was a single class, then we realized that it was doing about ten things, and was over 1000 lines. Oops. It was refactored into separate objects, some of which actually turned out to belong in the business layer.  So it appeared that we allowed the business layer to bleed into the controller. As the file was analyzed it was clear that a certain amount of methods and properties were only for a particular use and so these were extracted to a separate class. This was actually repeated multiple times for different uses, after which, the controller returned to just being a controller and it was a smaller easy to maintain class.

Future architecture changes

As the product continued to grow, other changes are seen as necessary even though they haven’t yet been implemented.

Separation of the Controller from the Business layer

A few of the business objects were for the Controller only and the rest of the business objects are for the ViewModel only. Since the Controller and Business layers are still in the same dll, this doesn’t yet matter. However, it was becoming clear as the project grew that the Controller has its business and the ViewModel/functionality had it Business and there is little overlap if any. It is likely that the Controller and Business layer will see a separation and decoupling where the Controller no longer references the Business layer and the business classes used by the Controller is just part of the Controller.

View communication with the DataContext without binding

There arose instances where binding was not supported or did not exist. In many cases we used attached properties or an inherited object and added the missing bindings, however, in some instances this didn’t make sense. What if the View needed to send a message to the DataContext or pass and event to the code behind and neither inheriting the object to add the binding or using an attached property made sense. What made sense was an interface.

I recently posted an article on Creating an Interface for data binding in Views with WPF. Imagine a new layer that exists between the View and the ViewModel called IViewModel. Both the View and the ViewModel reference it and they still don’t reference each other. An interface in the IViewModel project/dll would mainly include properties that help the ViewModel know what is needed for binding. However, in such rare circumstances that it makes sense to communicate to the DataContext, the View can check if the DataContext implements an interfaces and calls a method the interface defines.

Creating an Interface for data binding in Views with WPF

Perhaps you have seen the same idea as me. A list of bound objects and an interface with a list of properties, have a lot in common. To start with, both are contracts. By adding Bindings in WPF, you are creating a contract that promises any code that uses the view that if such code has certain properties to bind to, the view will bind to them. Similarly an interface is a contract wherein an object that implements the interface is required to comply with the interface else a build error.

Look at the following UserControl view.

<UserControl x:Class="BindingsAsInterfaceExample.View.PeopleView"
             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"
             mc:Ignorable="d"
             d:DesignHeight="200"
             d:DesignWidth="300"
             >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <DataGrid ItemsSource="{Binding People}" Grid.Row="0" Grid.ColumnSpan="3" HeadersVisibility="Column" CanUserAddRows="False" />
        <Button Content="Add Person" Command="{Binding AddPersonCommand}" Grid.Row="1" Grid.Column="0" />
        <Button Content="Edit Person" Command="{Binding EditPersonCommand}" Grid.Row="1" Grid.Column="1" />
        <Button Content="Delete Person" Command="{Binding DeletePersonCommand}" Grid.Row="1" Grid.Column="2" />
    </Grid>
</UserControl>

There are four bindings in this view. It may be beneficial to make these bindings into a concrete contract using an interface.

public interface IPeopleViewBindings
{
    IList People { get; set; }
    ICommand AddPersonCommand { get; set; }
    ICommand EditPersonCommand { get; set; }
    ICommand DeletePersonCommand { get; set; }
}

Then when implementing the view model, have it implement the interface. Now if some binding value is missing, a compile time error occurs.

using System.Collections;
using System.Collections.Generic;
using System.Windows.Input;
using BindingsAsInterfaceExample.Interfaces;
using BindingsAsInterfaceExample.Model;
using MVVM;

namespace BindingsAsInterfaceExample.ViewModel
{
    class PeopleViewModel : ViewModelBase, IPeopleViewBindings
    {
        #region Properties
        public IList People
        {
            get { return _People ?? (_People = CreateSamplePeople()); }
            set { _People = value; }
        } private IList _People;

        public ICommand AddPersonCommand
        {
            get
            {
                return _AddPersonCommand ??
                    (_AddPersonCommand = new RelayCommand(f => AddPerson(), f => AddPersonCanExecute()));
            }
            set { _AddPersonCommand = value; }
        } private ICommand _AddPersonCommand;

        public ICommand EditPersonCommand
        {
            get
            {
                return _EditPersonCommand ??
                    (_EditPersonCommand = new RelayCommand(f => EditPerson(), f => EditPersonCanExecute()));
            }
            set { _EditPersonCommand = value; }
        } private ICommand _EditPersonCommand;

        public ICommand DeletePersonCommand
        {
            get
            {
                return _DeletePersonCommand ??
                    (_DeletePersonCommand = new RelayCommand(f => DeletePerson(), f => DeletePersonCanExecute()));
            }
            set { _DeletePersonCommand = value; }
        } private ICommand _DeletePersonCommand;
        #endregion

        #region Functions
        private IList CreateSamplePeople()
        {
            IList people = new List<Person>();

            people.Add(new Person() { FirstName = "John", MiddleName = "J.", LastName = "Johnson" });
            people.Add(new Person() { FirstName = "Mark", MiddleName = "M.", LastName = "Markson" });
            people.Add(new Person() { FirstName = "Thom", MiddleName = "T.", LastName = "Thompson" });

            return people;
        }

        private void AddPerson()
        {
            // ...
        }

        private bool AddPersonCanExecute()
        {
            return true;
        }

        private void EditPerson()
        {
            // ...
        }

        private bool EditPersonCanExecute()
        {
            return true;
        }

        private void DeletePerson()
        {
            // ...
        }

        private bool DeletePersonCanExecute()
        {
            return true;
        }
        #endregion
    }
}

This is solution is not without problems.

  1. Now when you add a binding to a view, you have to remember to add it to the interface as well, otherwise you are no better off.
  2. Interfaces don’t support private fields and a lot of the methods are private.

However, it is actually quite useful when creating an API that someone else is consuming. Users of the API documentation will be grateful for the interfaces.

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

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.

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)

 

 

How to load a DictionaryStyle.xaml file at run time?

Changing a theme or style at run-time is possible by assigning styles using DynamicResource binding and loading a ResourceDictionary (XAML) from a Content file at run-time.

This can be done by loading a DictionaryStyle.xaml at run time.

If you would prefer to just jump right in, download the source code: RuntimeLoadOfResourceDictionaryExample.zip

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 – Create a basic WPF User Interface

  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 Blue or Grey for you.
  2. Set the Style to use DynamicResource binding.
  3. <Window x:Class="RuntimeLoadOfResourceDictionaryExample.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow"
            Style="{DynamicResource ResourceKey=MainWindowStyle}"
            >
        <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 Header="_Styles">
                        <MenuItem Name="BlueStyle" Header="_Blue" Click="MenuItem_Style_Click" />
                        <MenuItem Name="GreyStyle" Header="_Grey" Click="MenuItem_Style_Click" />
                    </MenuItem>
                </Menu>
            </DockPanel>
            <Label Content="First Name" Name="label1" Grid.Row="2" FlowDirection="RightToLeft" Grid.Column="1" />
            <Label Content="Age" Name="label3" Grid.Row="3" FlowDirection="RightToLeft" Grid.Column="1" />
            <Label Content="Last Name" Name="label2" Grid.Row="4" 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" />
        </Grid>
    </Window>
    
  4. Also populate the MainWindow.xaml.cs file with the code-behind needed for some of the events.
            private void MenuItem_Exit_Click(object sender, RoutedEventArgs e)
            {
                Environment.Exit(0);
            }
    
            private void MenuItem_Style_Click(object sender, RoutedEventArgs e)
            {
                MenuItem mi = sender as MenuItem;
                string stylefile = Path.Combine(App.Directory, "Styles", mi.Name + ".xaml");
                App.Instance.LoadStyleDictionaryFromFile(stylefile);
            }
    
  5. It won’t compile just yet as some of the code doesn’t exist yet.

Step 3 – Add code to read in a ResourceDictionary at runtime

This is going to take place in the App.xaml.cs file. App.xaml.cs is the ultimate parent and by loading the ResourceDictionary here, every child will have access to them. This especially becomes important with larger projects where WPF UI elements, controls, windows, or others may come from other dlls.

  1. Open the App.xam.cs file as shown below.
  2. Add a function to load the ResourceDictionary at runtime.
  3. Now add some member variables and create a constructor that loads a style by default.Your class should now look as follows:
    using System;
    using System.IO;
    using System.Windows;
    using System.Windows.Markup;
    
    namespace RuntimeLoadOfResourceDictionaryExample
    {
        /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App : Application
        {
            public static App Instance;
            public static String Directory;
            private String _DefaultStyle = "BlueStyle.xaml";
    
            public App()
            {
                Instance = this;
                Directory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
                string stringsFile = Path.Combine(Directory, "Styles", _DefaultStyle);
                LoadStyleDictionaryFromFile(stringsFile);
            }
    
            /// <summary>
            /// This funtion loads a ResourceDictionary from a file at runtime
            /// </summary>
            public void LoadStyleDictionaryFromFile(string inFileName)
            {
                if (File.Exists(inFileName))
                {
                    try
                    {
                        using (var fs = new FileStream(inFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            // Read in ResourceDictionary File
                            var dic = (ResourceDictionary)XamlReader.Load(fs);
                            // Clear any previous dictionaries loaded
                            Resources.MergedDictionaries.Clear();
                            // Add in newly loaded Resource Dictionary
                            Resources.MergedDictionaries.Add(dic);
                        }
                    }
                    catch
                    {
                    }
                }
            }
        }
    }
    

Now, we haven’t create the default style yet, don’t fret, that is the next step.

Step 4 – Create Some Styles

  1. In Visual Studio, add a new folder to your project called Styles.
  2. Right-click on the folder and choose Properties.
  3. Set the Namespace Provider value to false.
  4. Right-click on the Styles folder and choose Add | Resource Dictionary.
  5. Provide a file name and make sure that Resource Dictionary (WPF) is selected.
    Note: I named my first resource dictionary BlueStyle.xaml.
  6. Click Add.
  7. Right-click on the BlueStyle.xaml file and choose Properties.
  8. Set ‘Build Action’ to ‘Content’.
  9. Set ‘Copy to Output Directory’ to be ‘Copy if newer’.
  10. Set ‘Custom Tool’ to blank.
  11. Populate the BlueStyle.xaml with your desired style. Here is the simple style I used for this example.
    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Style x:Key="MainWindowStyle" TargetType="Window">
            <Setter Property="SizeToContent" Value="WidthAndHeight" />
            <Setter Property="Background" Value="RoyalBlue" />
        </Style>
        <Style TargetType="Label">
            <Setter Property="Margin" Value="0,5,0,5" />
        </Style>
        <Style TargetType="TextBox">
            <Setter Property="Margin" Value="0,5,0,5" />
        </Style>
    </ResourceDictionary>
    
  12. Create a copy of the style named GreyStyle.xaml.
  13. Repeat steps 7 thru 10 for this new file.
  14. In the GreyStyle.xaml, change the Background of the MainWindowStyle to DarkGrey.

Step 5 – Build and test

Your project should now be working.  You should be able to build and run it.  You should be able to click on Styles and change the style.