Showing posts with label WPF. Show all posts
Showing posts with label WPF. Show all posts

Tuesday, January 3, 2012

Using custom font in WPF application


INTRODUCTION 
Some time ago I needed to display some text in my WPF application using a custom font. As a custom font I see a font that is not installed in Fonts folder  in your (or the clients of your application) Operating System by default.  
It may seem that this is fairly easy task that should be done without any  problems in the way. After all, adding a custom font to your application is very similar to adding some image. And because displaying an image is not a big deal I was hoping that displaying a Label or TextBlock with custom font will also be relatively easy. But as I am going to show you, it is not. Tutorials and howto`s on the web take only the simplest scenario under consideration. A scenario that you will probably never see in a business application (all files being put into one folder). In this article I will present solution to this common scenario.
In the provided example I will use font downloaded from this site:http://www.1001freefonts.com/.
 
CUSTOM IMAGE VS. CUSTOM FONT 
As MSDN`s tutorials and good-practices state, if you intend to use some custom image in your application, you must first add it to your project and then ensure that ‘Build Action’ property is set to Resource: 
 
This will result in your image being compiled into the assembly which is pretty useful since there will be no separate file representing your image in your output directory. Therefore users of your application will find it impossible to change or download your graphics.
Exactly the same rules go for using a custom Font. So you should put it somewhere in your project directory, add it to the project using Solution Explorer and set it Build Action appropriately: 
Let’s get back to our Image. To display your image using the standard Image control it is enough to write: 
<Image Source="/WpfApplication10;component/Folder1/Water lilies.jpg" /> 
It is the most comfortable practice to generate this strangely-looking path with your Visual Studio designer. 
This is the point where custom image usage differs completely from custom font usage. MSDN [1] offers you two basic ways for applying font for a Label control (I shall be using label control in this article but the principles works as well for other similar controls like a TextBlock):  
"file:///d:/MyFonts/#Pericles Light"> 
Which is pretty useless since it uses absolute location – so it’s not a very flexible solution. Two developers working in one project may have the project files in two different location – in that case it wouldn’t work. Second possibility is: 
"./resources/#Pericles Light"> 
Which looks much better. When I saw at first I thought that this is just a simple way of referencing the font with an relative path. I thought that the dot ‘.’ points to the root of my project directory – just as always. So, if my project structure looks like this: 
and I would like to use my Katana font in Window2, I should write: 
"./Folder2/#Katana"> 
Which surprisingly doesn`t work at all. 
As it turned out the little dot ‘.’ points not to the root of my project directory but to the exact location of a Window or Control where it is used. So, in order to use this font I should write:
"../Folder2/#Katana"> 
Two dots ‘..’ of course mean that you want to go one step up in folders tree. But if such, this solution is also rather useless since it is not flexible at all. If you will change location of your Window where such font is used, then it will stop working. What’s more, it will stop working silently. You will not get any error, not even a warning. All elements that used that font before will now switch to use a default font. This is really not a nice behavior. What I really want is the way to set the path to my font relatively from the root of my application.  
 
SOLUTION 
Fortunately it Is possible. It involves using even more wicked string than before but works as expected: 
<LabelFontFamily="pack://application:,,,/Folder1/#Katana">TextLabel>
Three notes at the end:
  • ‘Katana’ is the name of the font, not the name of the file. This is significant difference. To get the name of the font simply click the file twice.
  • Remember to put the hash sign ‘#’ in front of font name. It will not work otherwise.
  • Custom font may also be added to the project with ‘Build Action’ set to ‘Content’. This is not recommended approach however and for the sake of simplicity I ignored this possibility.  

CONCLUSION 
Applying custom font to WPF application is certainly more complex and strange than it should be. There are a couple of articles in the Web that show how to deal with this issue but they all concern only about the simplest scenario – when all files are being put into one folder. In business application you are likely to have more complex folders tree – e.g. user controls put into one location, windows into another, and also another for resources like fonts. This is the most common scenario which is also the most poorly documented as well. I hope this article will help you in such situation.

Tuesday, December 6, 2011

Beginner's WPF Animation Tutorial

WpfApplication2

Introduction

My expected audience for this article is extreme beginners of WPF. But you should be knowledgeable in any of the .NET CLR languages. I used my favorite C# for description in this article. Also, do not forget, WPF is for .NET Framework 3.x+ and I used Visual Studio Express 2008.

Animate the Button

This tutorial is for creating a simple button animation with System.Windows.Media.Animation namespace. As usual, I use C# for demonstrating this sample since it is my favorite after C language. Also note that I write these articles for programmers and I will be writing code in C# even though we can do all these with XAML itself.
Step 1: Place a button on the form. We will call it Button1.
Step 2: Now add these lines to the button click event. (Simply double click on the button if you are in Visual Studio). Remember to set the language of your code snippet using the language dropdown.

DoubleAnimation da = new DoubleAnimation();
da.From = 30;
da.To = 100;
da.Duration = new Duration(TimeSpan.FromSeconds(1));
Button1.BeginAnimation(Button.HeightProperty, da);
Step 3: Press F5. i.e. Execute.
You will see a button increase its size automatically when you click.

Tips

  1. Add the following line before BeginAnimation. This will restore the button back after the animation. Of course it is also animated.
    da.AutoReverse = true;
  2. Add the following line before BeginAnimation. You can see that the animation never stops.
    da.RepeatBehavior = RepeatBehavior.Forever

Rotate Rectangle

WpfApplication2
Step 1: Place a button and shape rectangle on the form. (Button is not needed. I use it just for raising an event.)
Step 2: Add the following code in the button click event:
Note: Do not forget to import System.Windows.Media.Animation namespace.
DoubleAnimation da = new DoubleAnimation();
da.From = 0;
da.To = 360;
da.Duration = new Duration(TimeSpan.FromSeconds(3));
da.RepeatBehavior = RepeatBehavior.Forever;
RotateTransform rt = new RotateTransform();
rectangle1.RenderTransform = rt;
rt.BeginAnimation(RotateTransform.AngleProperty, da);
Step 3: Execute and enjoy. You can see a rectangle rotating 360 degrees continuously. As I mentioned in the other article, you can add autoreverse etc.
Here is the complete C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
 
namespace WpfApplication1
{
    /// 
    /// Interaction logic for Window1.xaml
    /// 
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation da = new DoubleAnimation();
            da.From = 0;
            da.To = 360;
            da.Duration = new Duration(TimeSpan.FromSeconds(3));
            da.RepeatBehavior = RepeatBehavior.Forever;
            RotateTransform rt = new RotateTransform();
            rectangle1.RenderTransform = rt;
            rt.BeginAnimation(RotateTransform.AngleProperty, da);
        }
    }
}

Artificially Rotate a Wheel

In this article, you can see a wheel picture at the top. We will use image1.RenderTransformOrigin to keep the centerpoint of the image. Check the sample source code attached.
Here is the code for 'running wheel':
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
 
namespace WpfApplication1
{
    /// 
    /// Interaction logic for Window1.xaml
    /// 
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            DoubleAnimation da = new DoubleAnimation
                (360, 0, new Duration(TimeSpan.FromSeconds(3)));
            RotateTransform rt = new RotateTransform();
            image1.RenderTransform = rt;
            image1.RenderTransformOrigin = new Point(0.5, 0.5);
            da.RepeatBehavior = RepeatBehavior.Forever;
            rt.BeginAnimation(RotateTransform.AngleProperty, da);
        }
    }
}
The animation procedure specified in this article is simply 'nothing' when compared to the scope hidden in WPF. Hope the fear that beginners have will be wiped out with this sample article. WPF is as simple as ABC.

DOWNLOAD SOURCE CODE

Do you need the source code of the project for your reference? Yes, you can download it from here:

Monday, November 28, 2011

Simplest Way to Implement Multilingual WPF Application


Introduction

Globalization is one of the concepts that comes to mind when we create applications that might run in different geographical locations. Based on the Culture code, we need to modify our application. This is a very common case for many developers. I thought let's discuss what I implemented as the most cunning way to deal with this in your WPF application.

Points of Interest

Globalization is the most common issue to every application. Many of us might have searched over time to find out the easiest way to do a Multilingual Application. Believe me, I did the same thing like you. After doing that, I found a lots of articles on the internet. For instance, you can see one from MSDN:
If you have already read the article, you might have found that there is no such actual implementation that clearly demonstrates the concept. That is why I thought of writing a concrete article for you to easily implement a truly Multilingual Application.

Using the Code

language.JPG
If you have downloaded the sample application, you can see that I have created a login screen, just to show how it works. To try, just run the application you will find a screen just like the one shown above.
Put Username and Password Same, and press login button. You will see the screen below:
language2.JPG
Next, go to Control Panel - > Regional & Language Option and change the Language to French(Canada), and Re run the application.
language3.JPG
You will find a different screen as below:
language1.JPG
And if you put credentials and press "connexion" (Login) button, you will see "Échec de l'authentification"(Authentication Failed).
Now I will discuss how can you implement this type of application yourself.

The Implementation

To start implementing this application, I have added one window. I have also designed the window with some look and feel. You can see them, but this is nothing to deal with our application, so I left out their implementation.
After creating the initial look and feel, which suits me, I added a folder named "Resources" (the name of which can be anything). I added two resource Dictionary to define my resource keys which I will use for my application.
language5.JPG

1. Creating the Resource File

The resource files are named as StringResources.xamlStringResource.fr-CA.xaml, etc. You can add as many resource files as you want, each of which corresponds to its own Culture.
Inside the resource files, you must declare the ResourceKeys. I have used system:String to define the Resources.
<ResourceDictionary 
      xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns: x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns: system="clr-namespace:System;assembly=mscorlib">

<system:String x:Key="close">Close</system:String>
<system:String x:Key="login">Login</system:String>

</ResourceDictionary> 
Thus you can see, in addition to adding the ResourceDictionary to the Resources Folder, I have added one namespace which points to mscorlib, and named it as system. I have then added the string references likecloselogin, etc. which are defined to be replaced in the UI.
Similar to this, I have added another file for fr-CA, and named it as StringResource.fr-CA.xaml. This will hold all the keys that corresponds to the Resourcekeys for a machine set up with French Canadian.
<ResourceDictionary 
        xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="close">Fermer</system:String>
<system:String x:Key="login">connexion</system:String>
</ResourceDictionary>
Thus you can see that I kept the same name for the keys to ensure everything works perfectly. If you have used ASP.NET Globalization, this is almost similar to it.

2. Adding a Resource

After you create the Resource file, it's time to add it to the window. To add, I have just implemented a method which you can place in some utility class. For simplicity, I left it in my window. The method looks like:
private void SetLanguageDictionary()
{
ResourceDictionary dict = new ResourceDictionary();
switch (Thread.CurrentThread.CurrentCulture.ToString())
{
  case "en-US":
       dict.Source = new Uri("..\\Resources\\StringResources.xaml",  
                     UriKind.Relative);
       break;
case "fr-CA":
        dict.Source = new Uri("..\\Resources\\StringResources.fr-CA.xaml", 
                           UriKind.Relative);
        break;
default :
        dict.Source = new Uri("..\\Resources\\StringResources.xaml", 
                          UriKind.Relative);
        break;
}
this.Resources.MergedDictionaries.Add(dict);
} 
This is the most simple implementation. I have added the dictionaries directly to the window resources. I have created an object of ResourceDictionary and pointed to the file that is created for resource to its Source property. This will load the external file directly to the object. And finally added to Window.Resources usingthis.Resources.MergedDirectories.Add(). As you know, after compiling, WPF holds the relative path intact, so it will not create any errors during runtime.

3. Using the Resource

Finally, it's now time to point ResourceKeys to your XAML to ensure it picks up the appropriate key from theResourceDictionary. Let us add some controls:
<Button      x:Name="btnLogin"
             Click="btnLogin_Click"
             Content="{DynamicResource login}"
             Grid.Row="3"
             Grid.Column="0" 
             Padding="10" 
/>
<Button x:Name="btnClose"
        Content="{DynamicResource close}"
        Click="btnClose_Click"
        Grid.Row="3"
        Grid.Column="1" 
        Padding="10" 
/> 
You should note that I have always put the Content of the Button using DynamicResource. This is important to define, because we want the content to be replaced with the appropriate key defined to the Resource will be added later.
Hence, your application is ready.

Points of Interest

You should note that you must define the key to the resource file before you use as DynamicResource. Otherwise, you will end up displaying nothing in the UI.
This implementation is totally based on UI elements, there is nothing to deal with translation of dynamic UI text. I will discuss about Translation of Language for dynamic User elements later in another article.

Conclusion

Thus, it is really fun to play with WPF, and as Multilingual application is most likely a common issue, I hope this article will help you in the long run. Try the sample application and see the actual implementation.


DOWNLOAD SOURCE CODE

Do you need the source code of the project for your reference? Yes, you can download it from here:

Wednesday, November 23, 2011

MVVM Pattern in WPF: A Simple Tutorial for Absolute Beginners


Introduction

As part of learning the MVVM pattern, I tried to search many sites and blogs and found most of them explained the pattern in a complicated way. After some research, I cracked the very basic steps in MVVM pattern, and here I am trying to write an MVVM tutorial for absolute beginners.
I don’t think much more time or words need to be spent for explaining the various parts of MVVM and the relationship between MVVM and WPF. If you travel to the depths of WPF, you will realize that MVVM is the best suitable pattern for WPF (you might not understand the difference between these two).
As a formal procedure, I am giving a simple diagram and definition for MVVM:
I start this tutorial with two examples: WpfSimple.csproj and WpfMvvmTest.csproj.
For the sake of simplicity, in the first project (WpfSimple.csproj), we are avoiding the Model object (an example with Model will come later).
In the example WpfSimple, the View contains just a Button and no code-behind, but the button click event is loosely bound with the ViewModel. The bindings between the View and ViewModel are simple to construct because a ViewModel object is set as the DataContext of a View. If property values in the ViewModelchange, those new values automatically propagate to the View via data binding. When the user clicks a button in the View, a command on the ViewModel executes to perform the requested action.

The View

The following code snippets are from the WpfSimple application (available with the tutorial):
<Window x:Class="WpfSimple.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfSimple"
        Title="MainWindow" Height="150" Width="370">
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
        <Grid>
        <Button Content="Click" 
                Height="23" 
                HorizontalAlignment="Left" 
                Margin="77,45,0,0" 
                Name="btnClick" 
                VerticalAlignment="Top" 
                Width="203"
                Command="{Binding ButtonCommand}" 
                CommandParameter="Hai" />
    </Grid>
</Window>
The ViewModel class used here is MainWindowViewModel, the object set as the DataContext of the View.

The ViewModel

The ViewModel class used over here is MainWindowViewModel.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows;

namespace WpfSimple
{
    class MainWindowViewModel
    {
        private ICommand m_ButtonCommand;
        public ICommand ButtonCommand
        {
            get
            {
                return m_ButtonCommand;
            }
            set
            {
                m_ButtonCommand = value;
            }
        }

        public MainWindowViewModel()
        {
            ButtonCommand=new RelayCommand(new Action(ShowMessage));
        }

        public void ShowMessage(object obj)
        {
            MessageBox.Show(obj.ToString());
        }
    }
}
You can see an empty code-behind file here. If you click on the button, it will prompt a message box, despite the lack of event handling methods in the Views. When the user clicks on buttons, the application reacts and satisfies the user's requests. This works because of bindings that were established on the Command property of Button displayed in the UI. The command object act as an adapter that makes it easy to consume a ViewModel's functionality from a View declared in XAML.

RelayCommand

RelayCommand is the custom class which is implemented in the ICommand interface. You can use any name instead of RelayCommand. Its usage is as follows: