Archive for the ‘ WPF ’ Category

Localization in WPF

I just got a question at work about how to do Localization in WPF, and fortunately we have done a pretty nice solution to that I must say. So why not post that here as well.

First of all, there are several ways to achieve localization in WPF, you can read Microsoft’s way of doing it here http://msdn.microsoft.com/en-us/library/ms788718.aspx . But I would like to do it in a somewhat different way. In my WPF application I use the MVVM design pattern, so wouldn’t it be nice if all resources are accessable through the View’s datacontext? So that you can data bind to the resource strings in the same way as you data bind to all other data in the ViewModel.

I’ll try to explain it for you here and provide you with some code snippets.

Continue reading

Advertisements

Highlight search result in WPF

Wouldn’t it be nice to easily see where in the search result that the search criteria are found? In the same way as most of today’s browsers do when you search for strings on the page, highlight all matches with yellow background.

I want to achieve the following result in WPF:

To be able to achieve the same effect in WPF, I thought I should implement my own TextBlock that has some extensions to it, dependency properties that you can bind to the search textbox. I thought my first attempt would be a custom control and then perhaps later see if it is possible to achieve the same effect with attached properties.

Continue reading

Persisting WPF control state

I would like to be able to easily save/persist the state of an element in WPF. In my current project we have a “desktop” with gadgets that you can move around; you have the possibility to change width and position on ListView columns. But the problem is that this is only stored in memory as the application is running. I would like to be able to easily write in xaml what properties and elements that should have its state persisted.

The first thing that came to my mind was Attached Properties. I just love attached properties and what you can achieve with them. I found a blog post by Tomer Shamam where he describes his implementation of exactly my problem. I downloaded the sample application he had, plugged the implementation into my project and viola, I can now easily Persist property values when closing and restarting my application. I did however change his implementation a bit to fully satisfy my needs, and also how the states are persisted. We need to save them in our database since our WPF application is running through Citrix and the users are using our application at several machines/terminals and therefore we need to save the user profile settings in a central repository.

Check out this blog if you want to know how to persist WPF control state.

http://blogs.microsoft.co.il/blogs/tomershamam/archive/2007/06/08/wpf-control-state-persistency.aspx

But in his solution you cannot save the order of columns in a ListView. So how should I do that?

Persisting WPF ListView Column Order

Let’s start by investigating what is happening when you move a column in a ListView. You can add an event handler to the GridView.Columns.CollectionChanged  event and from there get indication of what is happening.


((GridView)listView1.View).Columns.CollectionChanged += Columns_CollectionChanged;
void Columns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Move)   
    { … }
}

From NotifyCollectionChangedEventArgs you get the old index and new index for the column that you are moving.  We can then track all these changes to be able to later know exactly what moves that has been made on the columns collection and what order the columns has now.

The next problem is how do we easily move columns in a ListView? Fortunately there is a Move method on the columns collection


((GridView)listView1.View).Columns.Move(oldIndex, newIndex);

This method will move the specified item at the old index to a new index in the collection. So if we have done 10 column moves in the ListView and tracked all these in memory, we can then later reproduce the exact same moves using the Move method, this is what I would call a quick solution since we are probably doing a lot of moves that are unnecessary.

Instead let’s compare the original positions with the end result and from that calculate what minimal moves are needed to be able to achieve the same end result.

The implementation I ended up with removed and inserted the columns at their correct position during loading of the controls. But to be able to easily save the column order for each user I created a custom control that inherits ListView and provided a dependency property that is always up to date with the current column order as a string. For example, “3,0,1,2,4,5”, this means that column 3 in the original ListView is moved to be the first column in the end result.

I have a local field that holds the current column order


private List currentColumnOrder;

Event handler that updates the currentColumnOrder field to reflect moves made by the user

void Columns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Move)
    {
        var item = currentColumnOrder [e.OldStartingIndex];
        currentColumnOrder.RemoveAt(e.OldStartingIndex);
        currentColumnOrder.Insert(e.NewStartingIndex, item);
    }
}

Save

var columnOrder = string.Join(",",currentColumnOrder.Select(o => o.ToString()).ToArray());
// Set the ColumnOrder property to hold the current column order so that we can later persist it
// using ElementState Attached Properties
ColumnOrder = columnOrder;

Load

var indices = ColumnOrder.Split(',');
var tempColumns = new List();
foreach (var col in ((GridView)this.View).Columns)
{
    tempColumns.Add(col);
}
// Move columns to their proper position
for (int i = 0; i < indices.Length - 1; i++)
{
    var index = int.Parse(indices[i]);
    var col = tempColumns[index];
    // Only move column if it not in default position
    if (view.Columns[i] != col)
    {
        view.Columns.Remove(col);
        view.Columns.Insert(i, col);
    }
}

Xaml

<ctrls:PersistingListView

x:Name="SearchResultListView"

ItemsSource="{Binding SearchResult}"

SelectedItem="{Binding SelectedItem}"

ElementState.Mode="Persist"

ElementState.UId="ArticleSearchResultListView"

ColumnOrder="{PropertyState Default=''}">

<ListView.View>

<GridView

ElementState.Mode="PersistOrder"

ElementState.UId="ArticleSearchResultGridView">

<!--RowNumber-->

<GridViewColumn

Width="{PropertyState Default=40}"

ElementState.Mode="Persist"

ElementState.UId="ArticleSearchResultRowNumberColumn">

. . .

I cannot give you the complete code, but send me an email if you want more detailed source code.

Reduce frame rate for WPF animations to gain performance

 

Animations are very cool, but they can cause a high CPU load. One reason could be a missing hardware acceleration due to a old graphics adapter or a software rendering constraint. Another reason could be the the high frame rate of animations that is set to 60 fps by default.

You can easily lower the framerate for all animations by overriding the DesiredFrameRate property of the timeline. Just add the following code to your project and play around with the setting to find a good tradeoff between performance and aesthetic.

Timeline.DesiredFrameRateProperty.OverrideMetadata(typeof(Timeline),
   new FrameworkPropertyMetadata { DefaultValue = 30 });

Or you can set the framerate individually for each animation in XAML, using the following code:

<DoubleAnimation
    Storyboard.TargetProperty="Opacity"
    Duration="0:0:0.5" From="1.0" To="0.5"
    Timeline.DesiredFrameRate="30" />

In my current project we have a WPF application that is executed through Citrix. The frame rate has not been an issue until the application was run on a thin client/terminal with extremely limited resources and the application took 100% CPU when running the simplest animation. Our LOB WPF application does not have many animations but the once that are there are needed, so removing animations was out of the question. But we really don’t need 60 fps! So lowering frame rate to 15 made CPU performance go from 100% to 10% when animations was executed, and they all looked the same. Nice feature to know about!

Bypassing the Authenticode Signature Check on Startup

 

Authenticode verification will hurt startup time. I recently experienced this on a customer project. The initial startup time to show some parts of the UI took way to long first time accessing them. The WPF application is accessed through Citrix which also affects the startup performance for assemblies that needs to be verified.

Authenticode-signed assemblies need to be verified with the CA.  This verification can be time intensive, as it can require hitting the network several times to download up to date certificate revocation lists, and also to ensure that there is a full chain of valid certificates on the way to a trusted root.  This can, as in our case, end up in several seconds delay while that assembly is being loaded. Worst case for us was almost 30 sec for some client setups.

To get rid of this issue you can either install the CA certificate on the client machine or avoid using Authenticode when possible. We know that our application doesn’t need the Publisher evidence so we can do the following.

In .NET Framework 3.5 there is a configuration option that allows bypassing the Authenticode verification.  This can be done by adding adding the following lines to the .exe.config file:

<configuration>
        <runtime>
              <generatePublisherEvidence enabled="false"/>
       </runtime>
</configuration>

More information is available here as well as on this blog.

KB936707 discuss how you can also enable this in .NET Framework 2.0

%d bloggers like this: