Best wpf questions in January 2011

How not to lose binding source updates?

9 votes

Suppose I have a modal dialog with a textbox and OK/Cancel buttons. And it is built on MVVM - i.e. it has a ViewModel object with a string property that the textbox is bound to.

Say, I enter some text in the textbox and then grab my mouse and click "OK". Everything works fine: at the moment of click, the textbox loses focus, which causes the binding engine to update the ViewModel's property. I get my data, everybody's happy.

Now suppose I don't use my mouse. Instead, I just hit Enter on the keyboard. This also causes the "OK" button to "click", since it is marked as IsDefault="True". But guess what? The textbox doesn not lose focus in this case, and therefore, the binding engine remains innocently ignorant, and I don't get my data. Dang!

Another variation of the same scenario: suppose I have a data entry form right in the main window, enter some data into it, and then hit Ctrl+S for "Save". Guess what? My latest entry doesn't get saved!

This may be somewhat remedied by using UpdateSourceTrigger=PropertyChanged, but that is not always possible.

One obvious case would be the use of StringFormat with binding - the text keeps jumping back into "formatted" state as I'm trying to enter it.

And another case, which I have encountered myself, is when I have some time-consuming processing in the viewmodel's property setter, and I only want to perform it when the user is "done" entering text.

This seems like an eternal problem: I remember trying to solve it systematically from ages ago, ever since I've started working with interactive interfaces, but I've never quite succeeded. In the past, I always ended up using some sort of hacks - like, say, adding an "EnsureDataSaved" method to every "presenter" (as in "MVP") and calling it at "critical" points, or something like that...

But with all the cool technologies, as well as empty hype, of WPF, I expected they'd come up with some good solution.

At critical points, you can force the binding to push through to your view model:

var textBox = Keyboard.FocusedElement as TextBox;
BindingOperations.GetBindingExpression(textBox, TextBox.TextProperty).UpdateSource();

Edit:

OK, since you don't want hacks we have to face the ugly truth:

  • In order to implement a clean view, the properties exposed by your view model should be friendly to frequent binding updates.

An analogy we can use is a text editor. If the application was a giant text box bound to a file on disk, every keystroke would result in writing the whole file. Even the concept of saving is not needed. That's perversely correct but terribly inefficient. We all immediately see that the view model needs to expose a buffer for the view to bind to and this re-introduces the concept of save and forces state handling in our view model.

Yet, we see this is still not efficient enough. For even medium-sized files the overhead of updating the whole-file buffer on every keystroke becomes unbearable. Next we expose commands in our view model to efficiently manipulate the buffer, never actually exchanging the whole buffer with the view.

So we conclude that in order to achieve efficiency and responsiveness with pure MVVM, we need to expose an efficient view model. That means that all text boxes can be bound through to properties with no ill effects. But, it also means that you have to push state down into the view model to handle that. And that's OK because a view model is not the model; it's job is it to handle the needs of the view.

It's true that we can rapidly prototype user interfaces by taking advantage of shortcuts like binding on focus changes. But binding on focus changes can have negative consequences in real applications and if so then we should simply not use it.

What is the alternative? Expose a property friendly to frequent updates. Call it the same thing as the old inefficient property was called. Implement your fast property using the slow property with logic that depends on the state of the view model. The view model gets the save command. It knows whether the fast property has been pushed through to the slow property. It can decide if when and where the slow property will be synched to the model.

But you say, haven't we just moved the hack from the view to the view model? No, we have lost some elegance and simplicity, but go back to the text editor analogy. We have to solve the problem, and it is the view model's job to solve it.

If we want to use pure MVVM and we want efficiency and responsiveness, then lame heuristics like let's avoid updating the binding source until the element loses focus won't help. They introduce as many problems as they solve. In that case, we should let the view model do its job, even if means adding complexity.

Assuming we accept it, how can we manage the complexity? We can implement a generic wrapper utility class to buffer the slow property and allow the view model to hook its get and set methods. Our utility class can auto-register for save command events to reduce the amount of boilerplate code in our view model.

If we do it right, then all the parts of the view model that were fast enough to be used with property changed binding will all still be the same, and the others that were worthy of asking the question "Is this property too slow?" will have a small amount of code to address the issue, and the view is none the wiser.

TreeView Virtualization

8 votes

Hello, we're triyng to come up with a good way to virtualize the treeview, the data is not really a problem because it's very light (around 16 bytes per item), the problem is that we could potentially have tens of thousands, and although the actual data would only take 160 kb of memory, the treeview items do use a lot more memory. We've tried virtualization with 3 different trees now, WPF, Infragistics and Telerik. All of them have big issues that makes them unusable for our application:

WPF TreeView: The scroll bar shows some weird behavior, jumps around a lot, changes size inconsistently, scrolling by dragging it with the mouse doesn't work properly (jumps back and forth)

Telerik: Items dissapear, scroll bar is erratic too, items randomly expand collapse, styles don't work

Infragistics: Items are not virtualized at all, every item remains in memory making virtualization useless.

We've been struggling with this a couple of months now, and we haven't been able to find a good solution. Has any of you successfully implemented virtualization in a TreeView with more than 9000 items? If so, what was your strategy? Did you use third party controls? Did it work 100%?

Any suggestion extremely appreciated.

Thanks.

We've used Bea Costa's Stollnitz's trick of indenting items in a ListView and using UI Virtualization to good effect.

http://www.beacosta.com/blog/?p=45

I've gotten 100,000 items in the backing ICollectionView, and it is still quite responsive to filtering, etc.

When NOT to use MVVM?

8 votes

I have started using MVVM pattern recently. I have had several projects where I used it and with every new one, I start to see that it will fit great within that new project.

And now I start to ask myself are there situation when it's better NOT to use MVVM. Or is it such a nice pattern which you can use anywhere?

Could you please describe several scenarios where MVVM wouldn't be the best choice?

I can think of two circumstances under which I wouldn't use MVVM.

One is if the application's simple enough that I don't need a separation between the view model and the model. Does it muck up my class too much if I implement INotifyPropertyChanged and a RelayCommand or two? If not, I might skip the step of creating a separate class. Or I may just want a view model to mock up a functional UI, and worry about implementing actual back-end functionality if the client bites.

The other is when I need high enough performance, and there are enough objects in the view, that I need to write code that manipulates WPF objects directly. I haven't actually benchmarked it to be sure, but I'm be reasonably certain that drawing 1000 moving particles by iterating through an array containing them and modifying their TranslateTransform directly (if indeed that's the fastest way to position them) is going to be faster than modifying their base properties and having binding do it.

Generic way to exit a .NET application

8 votes

I understand that there are a few ways to exit an application, such as Application.Exit(), Application.ExitThread(), Environment.Exit(), etc.

I have an external "commons" library, and I'm trying to create a generic FailIf method that logs the failure to the logs, does this and that and this and that, then finally exits the application... here's a short version of it.

    public static void FailIf(Boolean fail, String message, Int32 exitCode = 1)
    {
        if (String.IsNullOrEmpty(message))
            throw new ArgumentNullException("message");

        if (fail)
        {
            //Do whatever I need to do

            //Currently Environment.Exit(exitCode)
            Environment.Exit(exitCode);
        }
    }

I have read that using Environment.Exit isn't the best way to handle things when it comes to WinForm apps, and also when working with WPF apps and Silverlight there are different ways to exit... My question is really:

What do I put to exit gracefully to cover all application types?

Read this about the difference between using Environment and Application :

Application.Exit Vs Environment.Exit

There's an exmple of what you want to do in the bottom of that page:

If (System.Windows.Forms.Application.MessageLoop)
{
  // Use this since we are a WinForms app
  System.Windows.Forms.Application.Exit()
}
Else
{
  // Use this since we are a console app
  System.Environment.Exit(1)
}

TextBox doesn't honor System Decimal (Dot or Comma)

8 votes

If I bind Text in a TextBox to a float Property then the displayed text doesn't honor the system decimal (dot or comma). Instead it always displays a dot ('.'). But if I display the value in a MessageBox (using ToString()) then the correct System Decimal is used.

enter image description here

Xaml

<StackPanel>
    <TextBox Name="floatTextBox"
             Text="{Binding FloatValue}"
             Width="75"
             Height="23"
             HorizontalAlignment="Left"/>
    <Button Name="displayValueButton"
            Content="Display value"
            Width="75"
            Height="23"
            HorizontalAlignment="Left"
            Click="displayValueButton_Click"/>
</StackPanel>

Code behind

public MainWindow()
{
    InitializeComponent();
    FloatValue = 1.234f;
    this.DataContext = this;
}
public float FloatValue
{
    get;
    set;
}
private void displayValueButton_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show(FloatValue.ToString());
}

As of now, I've solved this with a Converter that replaces dot with the System Decimal (which works) but what's the reason that this is neccessary? Is this by design and is there an easier way to solve this?

SystemDecimalConverter (in case someone else has the same problem)

public class SystemDecimalConverter : IValueConverter
{
    private char m_systemDecimal = '#';
    public SystemDecimalConverter()
    {
        m_systemDecimal = GetSystemDecimal();
    }
    object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value.ToString().Replace('.', m_systemDecimal);
    }
    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value.ToString().Replace(m_systemDecimal, '.');
    }
    public static char GetSystemDecimal()
    {
        return string.Format("{0}", 1.1f)[1];
    }
}

Looks like there's a solution for this:

http://www.nbdtech.com/Blog/archive/2009/03/18/getting-a-wpf-application-to-pick-up-the-correct-regional.aspx

Here is another discussion that can possibly help:

http://connect.microsoft.com/VisualStudio/feedback/details/442569/wpf-binding-uses-the-wrong-currentculture-by-default

Learning ASP.NET MVC with solid WPF/.NET background

8 votes

I have a solid .NET background except ASP.NET MVC, which I'd like to pick up. In particular I've got a lot of experience with WPF (MVVM), various flavors of Silverlight, LINQ (POCO and XML) and of course the core framework (C#, VB and recently F# as well).

What I'm missing and could be relevant is (obviously besides ASP.NET MVC) LINQ to SQL and the Entity Framework.

I know the basics of "plain old" ASP .NET (but really not that much beyond the basics), but I'm no stranger to SQL, HTML, CSS, JS, etc.

The question: if you did learn ASP.NET MVC3 starting from a background similar to mine, what approach have you found to be the effective (or not) and thus would recommend?

Note: I should mention that I'm interested in best practices and patterns as well. I found out at my expense that this is maybe more important than learning "how stuff work" (for ex. almost every WPF book teaches you everything about templates, binding, etc. but don't mention MVVM or other patterns that are fundamental for a large project).

I tend to read the blogs of some of the developers on the ASP.NET MVC team as well as some other individuals that have good insight into the framework:

  1. Phil Haack
  2. Steve Sanderson
  3. Brad Wilson
  4. Scott Hanselman
  5. Scott Gu (Normally does release announcements and introductions to new features)

Also, this link post by Scott Hanselman has a bunch of ASP.NET MVC 3 links towards the middle that will help supplement the reading you can do at www.asp.net/mvc

Specify which Property goes between `>` and `<` in Xaml

7 votes

Consider the following Xaml

<Grid>
    <TextBox>Text</TextBox>
    <Button>Content</Button>
</Grid>

It will set the

  • Text Property of a TextBox (only WPF)
  • Content Property of a Button
  • Children Property of a Grid

But how is this specified? How do you specify which Property that goes between the > and< in Xaml?
Is this set by some metadata in the Dependency Property or what?

Thanks

There is a ContentPropertyAttribute that is applied to a class. WPF/Silverlight will use reflection to determine which property to use.

If you want to do this with a custom class, you can do it like so:

[ContentProperty("Bar")]
public class Foo : Control
{
    public static DependencyProperty BarProperty = DependencyProperty.Register(
        "Bar",
        typeof(int),
        typeof(Foo),
        new FrameworkPropertyMetaData(0));

    public int Bar
    {
        get { return (int)GetValue(BarProperty); }
        set { SetValue(BarProperty, value); }
    }
}

Then you could specify it in XAML like so:

<lcl:Foo>12</Foo>

Update

Since it is using reflection, you don't really need to do a DependencyProperty. For instance, this will also work:

[ContentProperty("Bar")]
public class Foo : Control
{
    public int Bar { get; set; }
}   

Improve perceived WPF app startup time

7 votes

I have a WPF database viewer application: It's a simple main window containing a user control with a data grid showing the data extracted from an SQLite database.
The problem is that this application takes 6 seconds to start until it is usable.

I tried building the user control (and doing all the data loading) in the constructor of the main window:
The splash screen will be shown 5s this way, then followed by 1s of empty main window until the application is ready to be used.
Users said that it takes too long until something (visually) happens.

I then moved the user control creation (and data loading) into the Loaded event handler of the main window: The splash screen will be shown 3s, followed by 3s of empty main window until the application is ready.
Users said that it is "better", but don't like the fact that a half finished main window is shown in disabled state for so long.

Is there some general advice to be found about perceived application load time or are there any other recommendations about how this situation can be improved?
I believe ideally the main window would be shown as fast as possible, along with some hour glass or spinner until the data is loaded. But then I cannot just move the user control creation into a background worker as this would be done on the wrong thread.

Does anybody have any suggestions to this problem?

Edit:
Note that right now I've just assigned a LINQ-to-EF query as the grid data source.
One possible improvement may be to load this data into a data table in background and assign it only once loaded...

Edit2: I'm using .net 4 with System.Data.SQLite and EF4 to load the data. There are more or less 4000 rows and 30 columns.

Load your data asynchronous. Present something nice on the GUI for the user while loading. The following code can help you with this:

BackgroundWorker bgWorker = new BackgroundWorker() { WorkerReportsProgress=true};  
bgWorker.DoWork += (s, e) => {      
    // Load here your file/s      
    // Use bgWorker.ReportProgress(); to report the current progress  
};  
bgWorker.ProgressChanged+=(s,e)=>{      
    // Here you will be informed about progress and here it is save to change/show progress. 
    // You can access from here savely a ProgressBars or another control.  
};  
bgWorker.RunWorkerCompleted += (s, e) => {      
// Here you will be informed if the job is done. 
// Use this event to unlock your gui 
};  
bgWorker.RunWorkerAsync();  

The app is not faster but it seems to be much faster because the GUI is immediately visible and responsive. Maybe you also can show the user a part of the loaded data while loading the rest. Use the ProgressChanged-event for doing this.

Update

I'm not sure if I understand your problem right. If your problem is not the time data needs to be loaded, then something is odd in your application. WPF is IMO very fast. Control-creation does not takes a lot of time. I visualize much bigger lists as you mention in some milliseconds.

Try to look if you have something in your UI that hinders the DataGrid to virtualize the Items. Maybe you have a proplem there. To analyse WPF apps, I can recommend you the WPF Profiling Tools.

WPF doesn't apply style to first element

7 votes

I have a simple WPF window that has 12 buttons on it. I want the same style to be applied to all of them. This code produces the same error:

<Window x:Class="TestApp.TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TestWindow" Height="400" Width="500"
        WindowStyle="None" WindowState="Maximized">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resources/AllResources.xaml"/>
                <ResourceDictionary>
                    <Style TargetType="{x:Type Button}">
                        <Setter Property="FontSize" Value="100"/>
                    </Style>
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button Grid.Column="0" Content="1" Name="Button1"/>
        <Button Grid.Column="1" Content="2" Name="Button2"/>
    </Grid>
</Window>

The first button does not get the style applied to it, but the second one does. I could set a key and use that on every button, but I would prefer to let WPF handle that for me. I just found out while writing this that when I do not include the outside ResourceDictionary, it works as expected. This will be a problem in the future as my application expands as I have multiple windows that need to share the same resources. The modified code is as follows:

<Window x:Class="TestApp.TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TestWindow" Height="400" Width="500"
        WindowStyle="None" WindowState="Maximized">
    <Window.Resources>
        <Style TargetType="{x:Type Button}">
            <Setter Property="FontSize" Value="100"/>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button Grid.Column="0" Content="1" Name="Button1"/>
        <Button Grid.Column="1" Content="2" Name="Button2"/>
    </Grid>
</Window>

It also works if I (instead of removing the merged dictionaries) add an x:Key="key" attribute and then explicitly assign that style to each button.

What is the issue here? Why does the first one skip "Button1" and the second not?

I've seen this problem a couple of times before and it's a pretty weird "bug". It happends when you put a Style directly in a ResourceDictionary inside <ResourceDictionary.MergedDictionaries>. The Style is skipped for the first item. This code produces the same result, the Style is skipped for the first ListBoxItem

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="Foreground" Value="Green"/>
                </Style>
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>
<ListBox>
    <ListBoxItem Content="Item 1"/>
    <ListBoxItem Content="Item 2"/>
    <ListBoxItem Content="Item 3"/>
</ListBox>

The get both styles and MergedDictionaries to work, do it like this instead

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Resources/AllResources.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Style TargetType="{x:Type Button}">
            <Setter Property="FontSize" Value="100"/>
        </Style>
    </ResourceDictionary>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Button Grid.Column="0" Content="1" Name="Button1"/>
    <Button Grid.Column="1" Content="2" Name="Button2"/>
</Grid>

Why is a window larger in runtime?

7 votes

I have a window set to 340 x 146 px, not resizable.

In designer the window size is correct. But when I run the application it is bigger. enter image description here

Edit: Also, the layout is Canvas.

Classic theme:

enter image description here

Edit2:

After running snoop (thanks Zach), it appears that actual dimensions are what I specified. But the client area is bigger than one in visual studio.

I understand now that the client size stretches, when windows size is fixed to certain dimensions. However I think this makes Canvas layout in window unusable.

Edit3:

<Window x:Class="TI.Presentation.Views.AutentizationWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Authentication" Height="146" Width="340" ResizeMode="NoResize" Background="{StaticResource {x:Static SystemColors.ControlBrushKey}}" >
    <Canvas>
        <Label Canvas.Left="12" Canvas.Top="12" FontSize="15" Width="217">Enter authentication code here:</Label>
        <TextBox Canvas.Left="12" Canvas.Top="38" Height="23" Name="code" Width="294" FontSize="14" />
        <Button Canvas.Top="67" Content="OK" Height="28" Width="100" Canvas.Left="206" FontSize="14" IsDefault="True" Click="OKClick" />
    </Canvas>
</Window>

I'm going to answer this myself after poking around.

The window's ActualWith and ActualHeight are equal to Width and Height set in the designer.

What changes, is the client area. The dimensions of client are will be window dimensions minus theme border. This, however, breaks Canvas design because its absolutely positioned and canvas dimensions changed based on theme.

The way to make Canvas design work. Is to set dimensions on Canvas, remove dimensions on window and set SizeToContent on window accordingly. This way, cavnas dimensions stay fixed and Window size changes based on how think the theme border is.

Silverlight and WPF compatibility

7 votes

We are planning an application that will be both developed in Silverlight and WPF.

I wanted to know if, since we will be implemented the interface in XAML will it be compatible in both technologies?

What kind of problems should we expect when porting from one technology to another?

There are a couple of good sources on MSDN:

XAML Processing Differences Between Silverlight and WPF

WPF Compatibility

And also a good white-paper here:

http://wpfslguidance.codeplex.com/

There are a lot of similarities between WPF & Silverlight, this stems from Silverlight being mostly a subset of WPF. There are some entire API areas that Silverlight does not have, e.g. 3D, and also some smaller details like MultiBinding. The above links will help you understand the details.

My advice to you is to make Silverlight your primary target platform, almost everything that works in Silverlight will also work in WPF. Also, if you have the option, make sure you use the .NET 4.0 framework for WPF, which brings with it a few Silverlight features like VisualStateManager which were not previously in WPF.

It is a tricky process, but the potential rewards are quite big. I have managed to create a cross platform WPF / Silverlight / WP7 application that shares 75% of its code between platforms:

http://www.scottlogic.co.uk/blog/colin/2010/10/white-paper-silverlight-wpf-and-windows-phone-7-cross-platform-development/

C# Reflection why GetFields list fields that I haven't created ? How to exclude them ?

6 votes

This code returns fields that I created but also some system fields (I'm in WPF app) I didn't create myself:

FieldInfo[] fieldInfos;
fieldInfos = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

How to exclude the system fields and keep only my own ?

Update: these fields are not fields I inherited from my own class either.

I assume you have inherited from something other than object - in which case add DeclaredOnly to your GetFields call:

DeclaredOnly

Specifies that only members declared at the level of the supplied type's hierarchy should be considered. Inherited members are not considered.

So you would have:

FieldInfo[] fieldInfos = this.GetType().GetFields(
     BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);

Approach for a multi-lingual WPF application

6 votes

Hi,

it seems there are a number of approaches on how to implement multiple languages in a WPF application. But I would like some more information about what method I should be using with the following requirements:

  • It's a PRISM application, so a number of independent modules (assemblies) working together. I would like that each assembly has its own translations of UI elements.
  • I need a simple approach, no tools needed to generate stuff
  • Should still be able to use blend to design the UI
  • Optionally be able to switch language without restarting the application (not a dealbreaker)

Can someone advice me on how to achieve this?

Thanks!

Meanwhile I found an open source project that works really well: http://wpflocalizeextension.codeplex.com. It's just adding a reference to the dll, adding the resources with translations, and using it in XAML. It worked in 5 minutes. I can add multiple resources to individual modules; and it works fine in visual studio designer and blend. And, locale can be changed on the fly. Meets my requirements :)