wpf

Topics related to wpf:

Getting started with wpf

WPF (Windows Presentation Foundation) is Microsoft's recommended presentation technology for classic Windows desktop applications. WPF should not be confused with UWP (Universal Windows Platform) although similarities exist between the two.

WPF encourages data driven applications with a strong focus on multimedia, animation and data binding. Interfaces are created using a language called XAML (eXtensible Application Markup Language), a derivative of XML. XAML helps WPF programmers maintain separation of visual design and interface logic.

Unlike its predecessor Windows Forms, WPF uses a box model to layout all elements of the interface. Each element has a Height, Width and Margins and is arranged on screen relative to it's parent.

WPF stands for Windows Presentation Foundation and is also known under its Codename Avalon. It's a graphical Framework and part of Microsofts .NET Framework. WPF is pre-installed in Windows Vista, 7, 8 and 10 and can be installed on Windows XP and Server 2003.

MVVM in WPF

Models and View-Models

The definition of a model is often hotly debated, and the line between a model and a view-model can be blurred. Some prefer not to "pollute" their models with the INotifyPropertyChanged interface, and instead duplicate the model properties in the view-model, which does implement this interface. Like many things in software development, there is no right or wrong answer. Be pragmatic and do whatever feels right.

View Separation

The intention of MVVM is to separate those three distinct areas - Model, view-model, and View. While it's acceptable for the view to access the view-model (VM) and (indirectly) the model, the most important rule with MVVM is that the VM should have no access to the view or its controls. The VM should expose everything that the view needs, via public properties. The VM should not directly expose or manipulate UI controls such as TextBox, Button, etc.

In some cases, this strict separation can be difficult to work with, especially if you need to get some complex UI functionality up and running. Here, it's perfectly acceptable to resort to using events and event handlers in the view's "code-behind" file. If it's purely UI functionality then by all means utilise events in the view. It's also acceptable for these event handlers to call public methods on the VM instance - just don't go passing it references to UI controls or anything like that.

RelayCommand

Unfortunately the RelayCommand class used in this example isn't part of the WPF framework (it should have been!), but you'll find it in almost every WPF developer's tool box. A quick search online will reveal plenty of code snippets that you can lift, to create your own.

A useful alternative to RelayCommand is ActionCommand which is provided as part of Microsoft.Expression.Interactivity.Core which provides comparable functionality.

Introduction to WPF Data Binding

UpdateSourceTrigger

By default, WPF updates the binding source when the control loses focus. However, if there is only one control that can get focus -- something that's common in examples -- you will need to specify UpdateSourceTrigger=PropertyChanged for the updates to work.

You will want want to use PropertyChanged as the trigger on many two-way bindings unless updating the binding source on every keystroke is costly or live data validation is undesirable.

Using LostFocus has an unfortunate side effect: pressing enter to submit a form using a button marked IsDefault does not update the property backing your binding, effectively undoing your changes. Fortunately, some workarounds exist.

Please also note that, unlike UWP, WPF (4.5+) also has the Delay property in bindings, wich might just be enough for some Bindings with local-only or simple minor intelligence settings, like some TextBox validations.

Dependency Properties

WPF Architecture

WPF Localization

Content of controls can be localized using Resource files, just as this is possible in classes. For XAML there is a specific syntax, that is different between a C# and a VB application.

The steps are:

  • For any WPF project: make the resource file public, the default is internal.
  • For C# WPF projects use the XAML provided in the example
  • For VB WPF projects use the XAML provided in the example and change the Custom Tool property to PublicVbMyResourcesResXFileCodeGenerator.
  • To select the Resources.resx file in a VB WPF project:
    • Select the project in solution explorer
    • Select "Show all files"
    • Expand My Project

Creating Splash Screen in WPF

Value and Multivalue Converters

What IValueConverter and IMultiValueConverterthey are

IValueConverter and IMultiValueConverter - interfaces that provides a way to apply a custom logic to a binding.

What they are useful for

  1. You have a some type value but you want to show zero values in one way and positive numbers in another way
  2. You have a some type value and want to show element in one case and hide in another
  3. You have a numeric value of money but want to show it as words
  4. You have a numeric value but want to show different images for defferent numbers

These are some of the simple cases, but there are many more.

For cases like this, you can use a value converter. These small classes, which implement the IValueConverter interface or IMultiValueConverter, will act like middlemen and translate a value between the source and the destination. So, in any situation where you need to transform a value before it reaches its destination or back to its source again, you likely need a converter.

Styles in WPF

Introductory remarks

In WPF, a Style defines the values of one or more dependency properties for a given visual element. Styles are used throughout the application to make the user interface more consistent (e.g. giving all dialog buttons a consistent size) and to make bulk changes easier (e.g. changing the width of all buttons.)

Styles are typically defined in a ResourceDictionary at a high level in the application (e.g. in App.xaml or in a theme) so it is available app-wide, but they may also be defined for a single element and its children, e.g. applying a style to all TextBlock elements inside a StackPanel.

<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Margin" Value="5,5,5,0"/>
            <Setter Property="Background" Value="#FFF0F0F0"/>
            <Setter Property="Padding" Value="5"/>
        </Style>
    </StackPanel.Resources>
        
    <TextBlock Text="First Child"/>
    <TextBlock Text="Second Child"/>
    <TextBlock Text="Third Child"/>      
</StackPanel>

Important notes

  • The location where the style is defined affects where it is available.
  • Forward references cannot be resolved by StaticResource. In other words, if you're defining a style that depends upon another style or resource in a resource dictionary, it must be defined after/below the resource upon which it depends.
  • StaticResource is the recommended way to reference styles and other resources (for performance and behavioral reasons) unless you specifically require the use of DynamicResource, e.g. for themes that can be changed at runtime.

Resources

MSDN has thorough articles on styles and resources that have more depth than is possible to provide here.

WPF Resources

Thread Affinity Accessing UI Elements

Slider Binding: Update only on Drag Ended

  • Make sure to reference the System.Windows.Interactivity assembly, so that the XAML Parser will recognize the xmlns:i declaration.
  • Note that the xmlns:b statement matches the namespace where the behavior implementation resides
  • Example assumes working knowledge of binding expressions and XAML.

Supporting Video Streaming and Pixel Array Assignment to an Image Control

  • Make sure to reference the System.Windows.Interactivity assembly, so that the XAML Parser will recognize the xmlns:i declaration.
  • Note that the xmlns:b statement matches the namespace where the behavior implementation resides
  • Example assumes working knowledge of binding expressions and XAML.
  • This behavior supports assigning pixels to an image in the form of a byte array - even though the Dependency Property type is specified as an IList. This works since the C# byte array implements the IList
  • interface.
  • Behavior achieves very high performance, and can be used for Video Streaming
  • Do not assign the image's Source Dependency Property- bind to the Pixels Dependency Property instead
  • The Pixels, PixelWidth, PixelHeight and PixelFormat properties must be assigned for the pixels to be rendered
  • Order of Dependency Property assignment does not matter

Grid control

Creating custom UserControls with data binding

Note that a UserControl is very different from a Control. One of the primary differences is that a UserControl makes use of a XAML layout file to determine where to place several individual Controls. A Control, on the other hand, is just pure code - there's no layout file at all. In some ways, creating a custom Control can be more effective than creating a custom UserControl.

Markup Extensions

Optimizing for touch interaction

WPF Behaviors

Speech Synthesis

System.Windows.Controls.WebBrowser

A key point to note, which is not obvious from the documentation, and you could go for years without knowing is that it defaults to behaving like InternetExplorer7, rather than your most up-to-date InternetExplorer installation (see https://weblog.west-wind.com/posts/2011/may/21/web-browser-control-specifying-the-ie-version ).

This cannot be fixed by setting a property on the control; you must either modify the pages being displayed by adding an HTML Meta Tag, or by applying a registry setting(!). (Details of both approaches are on the link above.)

For example, this bizarre design behaviour might lead you to get a message saying "Script Error"/"An error has occurred in the script on this page". Googling this error might make you think that the solution is to try to suppress the error, rather that understanding the actual problem, and applying the correct solution.

"Half the Whitespace" Design principle

Triggers

  • All triggers, except for EventTrigger must be defined within a <Style> element. An EventTrigger may be defined in either a <Style> element, or a control's Triggers property.
  • <Trigger> elements may contain any number of <Setter> elements. These elements are responsible for setting properties on the containing element when the <Trigger> element's condition is met.
  • If a property is defined in the root element markup, the property change defined in the <Setter> element will not take effect, even if the trigger condition has been met. Consider the markup <TextBlock Text="Sample">. The Text property of the proceeding code will never change based on a trigger because root property definitions take precidence over properties defined in styles.
  • Like bindings, once a trigger has been used, it cannot be modified.

An Introduction to WPF Styles