Archives for : May2014

Globalization and Localization in WPF – Some thoughts

A part of my responsibilities is globalization of our primary application. The application consists of a mix of WinForms and WPF. Localization of WinForms is done using the built-in mechanism provided, which sucks. That right, I said it, it sucks. You identify the window/control as localizable and then pick a language other than default. This will create a resource file for you of the chosen language. Anytime you change any values while the window/control is selected with a language chosen other than default, those values will be moved from the default Designer.cs (if they haven’t already been moved) into a default resource file for you and add your new values to the resource file for the language. This sounds well and good, like everything should be sunshine and rainbows. But it often moves in a ton of stuff that wasn’t changed, sometimes won’t move in stuff right, and sometimes wipes stuff from the Designer.cs and then somehow misses adding it to the resource file. I mean, having a Designer.cs is a serious pain to begin with, but to mess it and the resource files up is considerably more of a pain.

So I was hoping when it got to WPF things would get easier. But Microsoft doesn’t seem to have planned out globalization for WPF. It doesn’t mean they didn’t think about it. It just doesn’t seem like developer experience was a part of the thought process. If you want to read what Microsoft has to day on the subject check out Globalization and Localization but I’ll give a quick summary below.

The first method they give has to do with using msbuild to add x:Uid attributes to all your xaml and another tool, LocBaml Tool, to generate satellite assemblies that contain the translated dlls. If you have names in all your xaml this might be nice. You’d have to set up a post-build process to generate the satellite assemblies but it’s not too bad. The problem, however, is if you’re doing MVVM dev. Since we rarely name our controls, when the uids get auto-generated they look like x:Uid=”TextBlock_1″ which is pretty ugly and if you use the LocBaml tool to generate your file for translation, that uid is meaningless. I’m surprised this is the first method as it is the ugliest. They go into quite a bit of detail and leave the second and third methods nearly empty.

The second method they give is using ResourceDictionary. As mentioned examples are pretty anemic and there is a better sample over at codeproject called Globalization in WPF using ResourceDictionary. This is actually pretty nice. The best part about this one is that because you are dynamically changing the dictionary on the fly you’re values can change on the fly too if the user chooses to.

The third method, and the one I ultimately choose was to use resource files with static references to the resource properties. The single example Microsoft gives is useless so check out WPF Localization for Dummies. I choose this method only because that is how localization is done in WinForms and since our application is a blend of both WinForms and WPF it made sense to be consistent.

Now obviously for any project of real size, just using the resource file in the Properties isn’t going to help. You’ll end up with a ton of strings and images in here that just starts looking horrible and becomes hard to manage. I’ve thrown together a sample project that shows using a resource file for English and Spanish. Note that I’ve directly modified the project file to identify that the resource files are dependent upon MainWindow.xaml. I’m not sure if there’s an easier way to do this but I just add the dependentUpon element in the project xml. This just makes the solution a little bit cleaner. Also notice that I named it MainWindowResx, this is to prevent class name conflicts as the name of the resource class will be the name of the file.

It is important to remember, once you add the resource file, that you open it in the designer and change the “AccessModifier” from internal to public. The problem is that the class will default to internal but will still not allow xaml to find the value. To fix this you need to make the AccessModifier public. Otherwise you will get a “StaticExtension value cannot be resolved to an enumeration, static field, or static property.” exception.

So after doing all this work to get things ready for globalization I began to think there had to be a better way. I’m not sure if the better path is a Visual Studio Extension or if it should be a custom tool that sits external and modifies the project file. This is something I’ll write about on and off as I work on the project in my personal time. If you have any feedback as I’m going through the process please feel free to leave comments or email me.

Thanks,
Brian

In the Prism 4.1 Developer’s Guide there was a multi-purpose object, DomainObject, that implemented INotifyPropertyChanged and INotifyDataErrorInfo. This was a nice generalized object to inherit from in MVVM. In models where I need to implement DataContract this was nice because I can just throw in the [DataContract(IsReference = true)] attribute so I can serialize.

The problem is that DomainObject uses ValidateProperty(“PropertyName”) and RaisePropertyChanged(“PropertyName”) instead of the SetProperty(ref _holder, value) and OnPropertyChanged(() => Property) that BindableBase uses. To start with I despise strings in code unless it is explicitly intended to be the text a user should see. I also would like to make everything consistent. It would be nice to just extend BindableBase but since it doesn’t implement DataContract I can’t. Not only that but I want to add validation and implement INotifyDataErrorInfo.

Fortunately, since Prism is open-source we can dive into the code and figure out how they implemented BindableBase and add that code to our own DomainObject while still implementing INotifyDataErrorInfo.

[DataContract(IsReference = true)]
public abstract class DomainObject : INotifyPropertyChanged, INotifyDataErrorInfo
{
	protected DomainObject() { }

	#region INotifyPropertyChanged Members

	public event PropertyChangedEventHandler PropertyChanged;

	/// <summary>
	/// sets the storage to the value
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="storage"></param>
	/// <param name="value"></param>
	/// <param name="propertyName"></param>
	/// <returns>True if the value was changed, false if the existing value matched the desired value.</returns>
	protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
	{
		ValidateProperty(propertyName, value);

		if (object.Equals(storage, value)) return false;

		storage = value;
		OnPropertyChanged(propertyName);

		return true;
	}

	/// <summary>
	/// Notifies listeners that a property value has changed.
	/// </summary>
	/// <param name="propertyName">Name of the property used to notify listeners. This
	/// value is optional and can be provided automatically when invoked from compilers
	/// that support <see cref="CallerMemberNameAttribute"/>.</param>
	protected void OnPropertyChanged(string propertyName)
	{
		var eventHandler = this.PropertyChanged;
		if (eventHandler != null)
		{
			eventHandler(this, new PropertyChangedEventArgs(propertyName));
		}
	}

	/// <summary>
	/// Raises this object's PropertyChanged event.
	/// </summary>
	/// <typeparam name="T">The type of the property that has a new value</typeparam>
	/// <param name="propertyExpression">A Lambda expression representing the property that has a new value.</param>
	protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
	{
		var propertyName = Microsoft.Practices.Prism.Mvvm.PropertySupport.ExtractPropertyName(propertyExpression);
		this.OnPropertyChanged(propertyName);
	}

	#endregion

	#region INotifyDataErrorInfo Members

	private ErrorsContainer<string> errorsContainer;

	public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged = delegate { };

	protected ErrorsContainer<string> ErrorsContainer
	{
		get
		{
			if (errorsContainer == null)
			{
				errorsContainer =
					new ErrorsContainer<string>(pn => OnErrorsChanged(pn));
			}

			return this.errorsContainer;
		}
	}

	public IEnumerable GetErrors(string propertyName)
	{
		return ErrorsContainer.GetErrors(propertyName);
	}

	public bool HasErrors
	{
		get { return ErrorsContainer.HasErrors; }
	}

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

	protected void OnErrorsChanged<T>(Expression<Func<T>> propertyExpression)
	{
		var propertyName = Microsoft.Practices.Prism.Mvvm.PropertySupport.ExtractPropertyName(propertyExpression);
		OnErrorsChanged(propertyName);
	}

	#endregion

	#region property validation

	protected void ValidateProperty(object value, [CallerMemberName] string propertyName = null)
	{
		ValidateProperty(propertyName, value);
	}

	protected virtual void ValidateProperty(string propertyName, object value) { }

	#endregion
}

So let’s look at this wall of code. First, on line 18 SetProperty is implemented, almost identical to how BindableBase in Prism 5 is. The awesome thing is the use of the Caller Information attribute, CallerMemberName, that was added in C# 5. CallerMemberName, when calling from a get or set, is the name of the property. This makes the boilerplate code a lot cleaner, as noted in my previous post on upgrading to Prism 5. The only real difference here is that I call ValidateProperty, which is optionally implemented in the models that extend from DomainObject. Most of the time nothing happens but there are times where errors get added to the ErrorsContainer because the model implements ValidateProperty.

The other cool thing from BindableBase is the use of Expression<Func> propertyExpression that then extracts the property name. This makes the code a lot cleaner since you can just pass in () => Property. The original DomainObject used slightly different terminology with RaisePropertyChanged and RaiseErrorChanged. In the above code, at lines 36 and 88 you can see I’ve changed the methods to be the consistent with BindableBase. Again, this is all so I can get the benefits of INotifyPropertyChanged and INotifyDataErrorInfo while still being able to utilize DataContract. Your situation may be differently than mine but this provides a generalized class that has made MVVM easier for me.

Thanks,
Brian

Adapter Design Pattern – A Real World Example

I think the simplest design pattern we’ve all used without really calling it a pattern, other than observer, is the adapter design pattern. The adapter design pattern is known more colloquially as a wrapper where you wrap a bunch of functionality from one or more classes into a single class because of incompatibilities between the interfaces.

In my post, Observer and Command Design Patterns – A Real World Example I discussed the need for the interfaces:

public interface IOpenDialog
{
	string Filter { get; set; }
	string FileName { get; set; }
	string[] FileNames { get; set; }
	bool Multiselect { get; set; }
	bool? ShowDialog();
}

public interface ISaveDialog
{
	string Filter { get; set; }
	string FileName { get; set; }
	string[] FileNames { get; set; }
	bool? ShowDialog();
}

These are modified a bit from the original interfaces I showed but you get the idea.

See, the problem comes when running your unit tests. I had a need in my view models where I wanted to open files and save files. But if I had used the standard dialogs from the Microsoft.Win32 namespace when I ran my unit tests things would just not have worked. I mean, how do I show a SaveFileDialog in a unit test?  There is some stuff I could have done with binding and listening for a property changed event in my view, that would have an ugly, unnecessary hack.

This is all made easier just by wrapping the SaveFileDialog and OpenFileDialog classes.

public class OpenFile : IOpenFileDialog
{
	#region IOpenDialog Members

	public string Filter { get; set; }
	public string FileName { get; set; }
	public string[] FileNames { get; set; }
	public bool Multiselect { get; set; }

	public bool? ShowDialog()
	{
		OpenFileDialog ofd = new OpenFileDialog();
		ofd.Filter = Filter;
		ofd.FileName = FileName;
		ofd.Multiselect = Multiselect;

		bool? result = ofd.ShowDialog();
		if (result == true)
		{
			FileName = ofd.FileName;
			FileNames = ofd.FileNames;
		}

		return result;
	}

	#endregion
}

public class SaveFile : ISaveFileDialog
{
	#region ISaveDialog Members

	public string Filter { get; set; }
	public string FileName { get; set; }
	public string[] FileNames { get; set; }

	public bool? ShowDialog()
	{
		SaveFileDialog sfd = new SaveFileDialog();
		sfd.Filter = Filter;
		sfd.FileName = FileName;

		bool? result = sfd.ShowDialog();
		if (result == true)
		{
			FileName = sfd.FileName;
			FileNames = sfd.FileNames;
		}

		return result;
	}

	#endregion
}

Since opening the dialogs in the view model is not possible, by utilizing the above classes (which wrap the standard dialogs) we abstract the dependencies away from the view model into the classes that implement the interface. Now all I have to do is register the types with my unity container:

container.RegisterType<ISaveFileDialog, SaveFile>();
container.RegisterType<IOpenFileDialog, OpenFile>();

And in my view models when I use it:

IOpenFileDialog ofd = container.Resolve<IOpenFileDialog>();
ofd.Filter = "Xml Files (*.xml)|*.xml";
if (ofd.ShowDialog() != true)
	return;

But in my mind there is an even cooler thing. In my NUnit project I have the two following classes in my Mocks directory:

public class OpenFileForUnitTest : IOpenFileDialog
{
	public bool? ShowDialogShouldReturn { get; set; }

	#region IOpenFileDialog Members

	public string Filter { get; set; }
	public string FileName { get; set; }
	public string[] FileNames { get; set; }
	public bool Multiselect { get; set; }

	public bool? ShowDialog()
	{
		return ShowDialogShouldReturn;
	}
	
	#endregion

	public OpenFileForUnitTest()
	{
		Flush();
	}

	public void SetFileNames(params string[] FileNamesToAdd)
	{
		FileNames = FileNamesToAdd;
		if (FileNamesToAdd == null || FileNamesToAdd.Length == 0)
		{
			FileName = null;
		}
		else
		{
			FileName = FileNamesToAdd[0];
		}
	}

	public void Flush()
	{
		Filter = null;
		FileName = null;
		FileNames = new string[0];
		Multiselect = false;
		ShowDialogShouldReturn = true;
	}
}

public class SaveFileForUnitTest : ISaveFileDialog
{
	public bool? ShowDialogShouldReturn { get; set; }
	public bool IgnoreFileNameSet { get; set; }
	
	#region ISaveFileDialog Members

	public string Filter { get; set; }
	
	string fileName;
	public string FileName
	{
		get { return fileName; }
		set
		{
			if (IgnoreFileNameSet)
				return;

			fileName = value;
		}
	}
	
	public string[] FileNames { get; set; }

	public bool? ShowDialog()
	{
		return ShowDialogShouldReturn;
	}

	#endregion

	public SaveFileForUnitTest()
	{
		Flush();
	}

	/// <summary>
	/// will override IgnoreFileNameSet to set FileName and then restore it
	/// </summary>
	/// <param name="FileNamesToAdd"></param>
	public void SetFileNames(params string[] FileNamesToAdd)
	{
		FileNames = FileNamesToAdd;
		bool ignore = IgnoreFileNameSet;
		IgnoreFileNameSet = false;
		if (FileNamesToAdd == null || FileNamesToAdd.Length == 0)
		{
			FileName = null;
		}
		else
		{
			FileName = FileNamesToAdd[0];
		}
		IgnoreFileNameSet = ignore;
	}

	public void Flush()
	{
		Filter = null;
		FileName = null;
		FileNames = new string[0];
		ShowDialogShouldReturn = true;
		IgnoreFileNameSet = false;
	}
}

And in my unit tests similar to how it’s used:

var ofd = new OpenFileForUnitTest();
container.RegisterInstance<IOpenFileDialog>(ofd);
ofd.SetFileNames(pathToTestFile);

var myVM = new myVM();
myVM.MethodToTest();

And auto-magically the view model gets the path to the test file for the unit test. Following this is a bunch of asserts to ensure that the state and properties of the view model loaded as I expected from the test file.

That’s it for this week.

Thanks,
Brian

Upgrading to Prism 5.0 – BindableBase

I recently upgraded my TPL Samples solution to the latest Prism libraries. I’ve removed the references to the “lib” directory and added Prism as a nuget package. The first thing you’ll notice is that NotificationObject has been deprecated and replaced with Microsoft.Practices.Prism.Mvvm.BindableBase. This makes things really nice as we no longer have such horrible boilerplate code.

What used to be

private string currentState;
public string CurrentState
{
	get { return this.currentState; }
	set
	{
		if (this.currentState != value)
		{
			this.currentState = value;
			this.RaisePropertyChanged(() => this.CurrentState);
		}
	}
}

Now looks like:

private string currentState;
public string CurrentState
{
	get { return this.currentState; }
	set { SetProperty(ref this.currentState, value); }
}

You can see how much cleaner this code is. The SetProperty method in BindableBase will take care of firing any RaisePropertyChanged events for you as well as take care of any needed validation. Check out Upgrading from Prism Library 4.1, which is Microsoft’s guide on upgrading.

Thanks,
Brian

 

Update 05/15/14:

Well, after using this I’ve discovered validation still has to be implemented manually.  I’ll do a future post regarding this.

Brian

FormatException.com – Now on Azure

For the past year this blog has been getting been getting slower and slower.  I hosted on bluehost, which had been my hosting provider since I first started this blog six years ago.  Now, I never contacted bluehost to see if they could resolve the slow response issues.  For the five years prior to the slow down they were a wonderful, cheap provider.  And maybe if I had sent an email their way they could have helped me.  But I figured as a .NET developer maybe it was time to go Azure.  I have a few web projects in the planning stages and wanted to start with a low-entry point penetration into Azure.  The biggest issue I had in the port over to Azure was a problem with Azure detecting that I had changed my cname entry at my domain provider.  It took roughly 24 hours for them to pick up the change.

Now, everybody warns you that when you make changes to your DNS entries it could take as many as 3 days to propagate.  In reality, however, I’ve never had it take more then an hour, until now.  So that’s why I’ve been down for 24 hours.  But I’m back with a new, cooler look.  I’m still playing around with the css a bit but I like the new look and feel.

The cname taking a while to update is an issue that other people have had with some reports I say taking as much as 4 or 5 days.  Scott Hanselman has been a very obvious proponent of Azure and what it can provide for you.  He did a great session with us here at the Tucson .NET Users Group.  I let him know of my troubles.  They may seem rather mild but I couldn’t imagine being down even longer then I was.

So thanks for your continued patronage and here’s to another six years,

Brian