Localizing a WPF application
I know, Google knows so much about this, yet still, no clear and simple step-by-step guide. So here it goes:
- Download LocBaml tool here
- Compile it and get the LocBaml.exe
- Open your project file with Notepad.
- Add the following there: <UICulture>en-US</UICulture> under all <PropertyGroup> tags (for all build configs that is).
- In your XAML files add x:Uid="someUniqueUid" to any element you want to localize.
- Build your project.
- Navigate your explorer to the build folder - you will see that it has a new subfolder called en-US. Inside you will find a file - YourProject.resources.dll
- Copy the binary of your project (e.g. YourProject.exe), LocBaml.exe and any referenced project binaries into this en-US folder.
- Open a command line prompt in this folder (under Windows seven you can press [Shift] + Right click and choose the command prompt window from the context menu).
- Run the following: locbaml /parse YourProject.resources.dll /out:YourProject.txt - a human-readable text file will appear in the folder.
- Edit the text file (translate the values in it). Excel is your best option - open the file from Excel menu and it will ask you if you want to treat tab symbols as text separators).
- Run the following after you localized the text file: locbaml /generate /trans:YourProject.txt /out:..\ru-RU /cul:ru-RU YourProject.resources.dll (replace ru-RU with the culture you are localizing into).
- Now all you have to do is to set the CultureInfo for your application thread like this:
var cultureInfo = new CultureInfo("ru-RU");
System.Threading.CurrentThread.CurrentCulture = cultureInfo;
System.Threading.CurrentThread.CurrentUICulture = cultureInfo;
And you are done. You app should be localized now!
HOW-TO: Creating a simple UserControl for displaying a FlowDocument
Hello. This is my first post about WPF.
This how-to will show you how to create a UserControl in which you can show a FlowDocument by passing a string containing the FlowDocument. It also allows Data Binding.
Lets start.
1. Create a UserControl called FlowDocumentViewer in Expression Blend (you can also do this in Visual Studio if you want) and add a FlowDocumentScrollViewer to LayoutRoot. Name it flowDocument (you can name it like you want, but I will be using this name in this guide). Your structure should be as follows:

2. Now, open the project in Visual Studio and add the following code to your FlowDocumentViewer.xaml.cs:
public static readonly DependencyProperty ContentFlowDocumentStringProperty = DependencyProperty.Register(
"ContentFlowDocumentString",
typeof(string),
typeof(FlowDocumentViewer),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(DescriptionFlowDocumentUI.OnContentChanged)
)
);
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FlowDocumentViewer control = (FlowDocumentViewer)d;
control.flowDocument.Document =
(System.Windows.Documents.FlowDocument)System.Windows.Markup.XamlReader.Load(
new MemoryStream(System.Text.UTF8Encoding.Default.GetBytes((string)e.NewValue))
);
}
public string ContentFlowDocumentString
{
get { return (string)GetValue(ContentFlowDocumentStringProperty); }
set { SetValue(ContentFlowDocumentStringProperty, value); }
}
Lets see what this code does.
a) We added a DependencyProperty called ContentFlowDocumentStringProperty to our class. This DependencyProperty "points" at ContentFlowDocumentString property, as well as it tells, that this property of type string and we registered a callback function (OnContentChanged), which will be triggered when ContentFlowDocumentString is changed. Note that FrameworkPropertyMetadataOptions.AffectsRender piece of code. This tells WPF, that when this property is changed it affects the UI looks, so that WPF knows he has to render something.
b) The OnContentChanged function is called whenever our DependencyProperty is changed. Here we do the actual work of changing the FlowDocument in our control. We get the instance as an argument (DependencyObject d, which we cast to FlowDocumentViewer explicilty) and we create a new FlowDocument from the newly assigned string ((string)e.newValue).
c) Finally we added the actual property - ContentFlowDocumentString. See those GetValue and SetValue? Don't be surprized, it is how DependencyProperties work. You don't have a special (private) field in your class for them. WPF does all the work for you.
Well, that is pretty much it.
The usage is simple:
FlowDocumentViewer fdv = new FlowDocumentViewer(); fdv.ContentFlowDocumentString = stringContainingFlowDocumentXAML;
Or if you want to use data binding, it is absolutely similar to casual binding in WPF:
Binding b = new Binding();
b.Source = myBindingSource;
b.Path = new PropertyPath("PathToProperty");
FlowDocumentViewer fdv = new FlowDocumentViewer();
fdv.SetBinding(FlowDocumentViewer.ContentFlowDocumentStringProperty, b);
If you have questions / remarks / etc. feel free to post them. I will try to answer.