Hidden features of WPF and XAML?

WpfXamlHidden Features

Wpf Problem Overview


Here is a large number of hidden features discussed for variety of languages. Now I am curious about some hidden features of XAML and WPF?

One I have found is the header click event of a ListView

<ListView x:Name='lv' 
      Height="150" 
      GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler">

The GridViewColumnHeader.Click property is not listed.

Some of relevant features so far:

See also:

  1. Hidden features of C#
  2. Hidden features of Python
  3. Hidden features of ASP.NET
  4. Hidden features of Perl
  5. Hidden features of Java
  6. Hidden features of VB.NET
  7. Hidden features of PHP
  8. Hidden features of Ruby
  9. Hidden features of C
  10. And So On........

Wpf Solutions


Solution 1 - Wpf

Multibinding (combined with StringFormat):

<TextBlock>
  <TextBlock.Text>
    <MultiBinding StringFormat="{}{0}, {1}">
      <Binding Path="LastName" />
      <Binding Path="FirstName" />
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>

Solution 2 - Wpf

There is also PresentationTraceSources.TraceLevel trick to debug what is going on with bindings in any particular scenario. All you have to do is to reference System.Diagnostics namespace in WindowsBase assembly

xmlns:sd="clr-namespace:System.Diagnostics;assembly=WindowsBase"

and then add following to the binding expression:

<TextBlock Text="{Binding Message, sd:PresentationTraceSources.TraceLevel=High}"  />

Log will be like this:

System.Windows.Data Warning: 52 : Created BindingExpression (hash=5923895) for Binding (hash=7588182)
System.Windows.Data Warning: 54 :   Path: 'Message'
System.Windows.Data Warning: 56 : BindingExpression (hash=5923895): Default mode resolved to OneWay
System.Windows.Data Warning: 57 : BindingExpression (hash=5923895): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 58 : BindingExpression (hash=5923895): Attach to System.Windows.Controls.TextBlock.Text (hash=65248697)
System.Windows.Data Warning: 63 : BindingExpression (hash=5923895): Resolving source 

Solution 3 - Wpf

3.5sp1 introduced StringFormat into binding expressions, e.g.

<TextBox Text="{Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}" />

Solution 4 - Wpf

3.5sp1 introduced TargetNullValue to bindings. This will set the bound property to Null if the value is entered and if your property is Null it will display this value.

<TextBox Text="{Binding Total, TargetNullValue=$0.00}" />

Solution 5 - Wpf

Sometimes you get string that is too long to show on label. In this case we can make use of TextTrimming property of TextBlock to show Ellipses

<TextBlock 
  Name="sampleTextBlock" 
  TextTrimming="WordEllipsis" 
  TextWrapping="NoWrap"/>

MSDN Link

Solution 6 - Wpf

Adding Aero effect to Window

  <Window.Resources>
    <ResourceDictionary Source="/PresentationFramework.Aero, Version=3.0.0.0, Culture=neutral, 
        PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/aero.normalcolor.xaml" />
</Window.Resources>

Solution 7 - Wpf

Generics in XAML with x:TypeArguments

If you want to use an ObservableCollection in XAML you need to create a type that derives from ObservableCollection because you cannot declare it in XAML. With XAML 2009 you can use the x:TypeArguments attribute to define the type of a generic type.

<!-- XAML 2006 -->
class EmployeeCollection : ObservableCollection<Employee>
{
}
    
<l:EmployeeCollection>
    <l:Employee FirstName="John" Name="Doe" />
    <l:Employee FirstName="Tim" Name="Smith" />
</lEmployeeCollection>
 
<!-- XAML 2009 -->
<ObservableCollection x:TypeArguments="Employee">
    <l:Employee FirstName="John" Name="Doe" />
    <l:Employee FirstName="Tim" Name="Smith" />
</ObservableCollection />

Solution 8 - Wpf

Show Tooltip on a disabled control

Wpf allows to show tooltip on a control, if it is in disabled state.

For example

<Button Content="Disabled Button" ToolTipService.ShowOnDisabled="True" IsEnabled="False" ToolTip="This is a disabled button"/> 

Solution 9 - Wpf

Use of Non-Default Constructors with x:Arguments

In XAML 2006 objects must have a public default constructor to use them. In XAML 2009 you can pass constructor arguments by using the x:Arguments syntax.

<!-- XAML 2006 -->
<DateTime>00:00:00.0000100</DateTime>

<!-- XAML 2009 -->
<DateTime>
    <x:Arguments>
        <x:Int64>100</x:Int64>
    </x:Arguments>
</DateTime>

Solution 10 - Wpf

Not really a hidden feature but with WPF/XAML you get Bea Stollnitz and Josh Smith. Queen and King of WPF/XAML programming.

Solution 11 - Wpf

Markup extensions and attached properties are my favorite features, they enable you to extend XAML "vocabulary" in a very elegant way.

Markup extensions

<!-- Binding to app settings -->
<CheckBox IsChecked="{my:SettingBinding MinimizeToTray}">Close to tray</CheckBox>

<!-- Fill ItemsControl with the values of an enum -->
<ComboBox ItemsSource="{my:EnumValues sys:DaysOfWeek}"/>

<!-- Localization -->
<TextBlock Text="{my:Localize HelloWorld.Text}"/>

<!-- Switch on the result of a binding -->
<TextBlock Text="{my:Switch Path=IsGood, ValueIfTrue=Good, ValueIfFalse=Bad}"/>

Attached properties

<!-- Sort GridView automatically -->
<ListView ItemsSource="{Binding Persons}"
      IsSynchronizedWithCurrentItem="True"
      util:GridViewSort.AutoSort="True">
    <ListView.View>
        <GridView>
            <GridView.Columns>
                <GridViewColumn Header="Name"
                                DisplayMemberBinding="{Binding Name}"
                                util:GridViewSort.PropertyName="Name"/>
                <GridViewColumn Header="First name"
                                DisplayMemberBinding="{Binding FirstName}"
                                util:GridViewSort.PropertyName="FirstName"/>
                <GridViewColumn Header="Date of birth"
                                DisplayMemberBinding="{Binding DateOfBirth}"
                                util:GridViewSort.PropertyName="DateOfBirth"/>
            </GridView.Columns>
        </GridView>
    </ListView.View>
</ListView>


<!-- Vista Glass effect -->
<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:WpfApplication1"
        Title="Window1"
        my:WinUtil.EnableAeroGlass="True">

...

Source for GridViewSort (btw, it uses the GridViewColumnHeader.Click event mentioned by Ortus)

Solution 12 - Wpf

You can refer to nested types in XAML using the plus sign (+). For example, if we had this class:

public class SomeClass
{
    public enum SomeEnum
    {
        SomeValue
    };
}

We could refer to SomeValue in XAML using the following syntax:

{x:Static local:SomeClass+SomeEnum.SomeValue}

This syntax is not documented on MSDN, and it is not officially supported. Someone asked about it on the MSDN forums, and apparently it breaks VS2010's WPF Designer. It has been reported on Microsoft Connect.

Solution 13 - Wpf

Grid size sharing (here's a good example). Long story short you can have grid columns and rows share sizes, even across different grids. This will be invaluable for all the people out there who are using DataGrids without the need to edit the data in place.

Solution 14 - Wpf

PriorityBinding. Allows you to use asyn bindings in an "first come first show" order:

<TextBlock.Text>
      <PriorityBinding FallbackValue="defaultvalue">
        <Binding Path="SlowestDP" IsAsync="True"/>
        <Binding Path="SlowerDP" IsAsync="True"/>
        <Binding Path="FastDP" />
      </PriorityBinding>
</TextBlock.Text>

Solution 15 - Wpf

Use of Static Factory Methods with x:FactoryMethod

When you have a type that has no public constructor but a static factory method you had to create that type in code in XAML 2006. With XAML 2009 you can use the x:FactoryMethodx:Arguments attribute to pass the argument values.

<!-- XAML 2006 -->
Guid id = Guid.NewGuid();

<!-- XAML 2009 -->
<Guid x:FactoryMethod="Guid.NewGuid" />

Solution 16 - Wpf

Advanced "caption" properties

Another thing that is not very clear is the contents of some properties that we are used to contains only text. If the property of a GUI element is of type Object, it is very likely that you can, instead of just setting the text, add a panel of your need that includes a set of controls.

An example of this is the MenuItem, where the Header property (which normally just contains text) can contain a set of gui elements wrapped in a panel control (or just one gui element if you need just one).

Also note the Icon property on the MenuItem. This normally contains an Image element, but this also can contain anything!

<MenuItem Name="MyMenuItem" Click="MyMenuItem_Click">
  <MenuItem.Icon>
    <Button Click="Button1_Click">i</Button>
  </MenuItem.Icon>
  <MenuItem.Header>
     <StackPanel Orientation="Horizontal" >
        <Label>My text</Label>
        <Button Click="Button2_Click">ClickMe!</Button>
     </StackPanel>
  </MenuItem.Header>
</MenuItem>

Solution 17 - Wpf

Solution 18 - Wpf

Built-in Types

If you want to add objects of simple types like string or double to a resource dictionary today you need to map the needed clr-namespaces to an XML namespaces. In XAML 2009 we a lot of simple types that are included in the XAML language.

<!-- XAML 2006 -->
<sys:String xmlns:sys="clr-namespace:System;assembly=mscorlib >Test</sys:String>

<!-- XAML 2009 -->
<x:String>Test</x:String>

The following types are included into the XAML language:

<x:Object/> 
<x:Boolean/> 
<x:Char/> 
<x:String/> 
<x:Decimal/> 
<x:Single/> 
<x:Double/> 
<x:Int16/> 
<x:Int32/> 
<x:Int64/> 
<x:TimeSpan/> 
<x:Uri/> 
<x:Byte/> 
<x:Array/> 
<x:List/> 
<x:Dictionary/> 

Solution 19 - Wpf

Easy Object References with {x:Reference}

If you want to create an object reference today you need to do a databinding and declare the source with an ElementName. In XAML 2009 you can use the new {x:Reference} markup extension

<!-- XAML 2006 -->
<Label Target="{Binding ElementName=firstName}">FirstName</Label>
<TextBox x:Name="firstName" />

<!-- XAML 2009 -->
<Label Target="{x:Reference firstName}">FirstName</Label>
<TextBox x:Name="firstName" />

Solution 20 - Wpf

System Colors Usage

<Border Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>

Solution 21 - Wpf

Support for Arbitrary Dictionary Keys

In XAML 2006 all explicit x:Key value were treated as strings. In XAML 2009 you can define any type of key you like by writing the key in ElementSyntax.

<!-- XAML 2006 -->
<StreamGeometry x:Key="CheckGeometry">M 0 0 L 12 8 l 9 12 z</StreamGeometry>

<!-- XAML 2009 -->
<StreamGeometry>M 0 0 L 12 8 l 9 12 z
    <x:Key><x:Double>10.0</x:Double></x:Key>
</StreamGeometry>

Solution 22 - Wpf

Set a ValidationError by Code

A ValidatioRule in a BindingExpression only triggers, when the target side of the binding changes. If you want to set a validation error by code you can use the following snippet.

Set the validation error

ValidationError validationError = 
    new ValidationError(regexValidationRule, 
    textBox.GetBindingExpression(TextBox.TextProperty));

validationError.ErrorContent = "This is not a valid e-mail address";

Validation.MarkInvalid(
    textBox.GetBindingExpression(TextBox.TextProperty), 
    validationError);

Clear the validation error

Validation.ClearInvalid(textBox.GetBindingExpression(TextBox.TextProperty));

Solution 23 - Wpf

The Ability to Stuff UIElement(s) into a TextBlock

I don't know how useful (it qualifies as hidden though) this is ... but it sure caught me off-guard when I first ran into it:

<Grid x:Name="LayoutRoot">
    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
        <Grid>
            <Rectangle Fill="AliceBlue" Width="25" Height="25"/>
        </Grid>
    </TextBlock>
</Grid>

You could argue the following xaml could be useful (i.e. putting a graphic at the end of some text):

<Grid>
    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="Hello World">
        <TextBlock.Resources>
            <DrawingBrush x:Key="exclamationPoint" Stretch="Uniform">
                <DrawingBrush.Drawing>
                    <DrawingGroup>
                        <DrawingGroup.Children>
                            <GeometryDrawing Brush="#FF375CE2" Geometry="F1 M 7.968,58.164L 0,58.164L 1.914,49.921L 9.882,49.921L 7.968,58.164 Z M 21.796,0L 11.054,42.148L 4.403,42.148L 13.049,0L 21.796,0 Z "/>
                        </DrawingGroup.Children>
                    </DrawingGroup>
                </DrawingBrush.Drawing>
            </DrawingBrush>
        </TextBlock.Resources>
        <Grid>
            <Rectangle Width="100" Height="100" Fill="{StaticResource exclamationPoint}"/>
        </Grid>
    </TextBlock>
</Grid>

The above xaml renders like the following:

Hello World

Solution 24 - Wpf

Debugging Animations

Common Errors

If you get the following error: Cannot animate '(0).(1)' on an immutable object instance. it could be that you are run into one of the following limitations:

  • You are animating a dependency property without setting a local value
  • You are animating a dependency property who's current value is defined in another assembly that is not merged into the resource dictionary.
  • You are animating a value that is currently databound

Solution 25 - Wpf

Binding without INotifyPropertyChanged or DependencyProperties

As discussed here you can bind a plain CLR object property without INotifyPropertyChanged, and it will just work.

Here is the Forumpost i am referring to.

Quote:

> [...] WPF's data binding engine will data bind to PropertyDescriptor instance which wraps the source property if the source object is a plain CLR object and doesn't implement INotifyPropertyChanged interface. And the data binding engine will try to subscribe to the property changed event through PropertyDescriptor.AddValueChanged() method. And when the target data bound element change the property values, data binding engine will call PropertyDescriptor.SetValue() method to transfer the changed value back to the source property, and it will simultaneously raise ValueChanged event to notify other subscribers (in this instance, the other subscribers will be the TextBlocks within the ListBox. > > And if you are implementing INotifyPropertyChanged, you are fully responsible to implement the change notification in every setter of the properties which needs to be data bound to the UI. Otherwise, the change will be not synchronized as you'd expect.[...]

Here is another great and detailed article on the subject.

> Note this only works when using binding. If you update the values from code, the change won't be notified. [...] > > Implementing INotifyPropertyChanged can be a fair bit of tedious development work. However, you'll need to weigh that work against the runtime footprint (memory and CPU) of your WPF application. Implementing INPC yourself will save runtime CPU and memory.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSauronView Question on Stackoverflow
Solution 1 - WpfJulien PoulinView Answer on Stackoverflow
Solution 2 - WpfidursunView Answer on Stackoverflow
Solution 3 - WpfBryan AndersonView Answer on Stackoverflow
Solution 4 - WpfBryan AndersonView Answer on Stackoverflow
Solution 5 - WpfPrashant CholachaguddaView Answer on Stackoverflow
Solution 6 - WpfSauronView Answer on Stackoverflow
Solution 7 - WpfSauronView Answer on Stackoverflow
Solution 8 - WpfSauronView Answer on Stackoverflow
Solution 9 - WpfSauronView Answer on Stackoverflow
Solution 10 - WpfBryan AndersonView Answer on Stackoverflow
Solution 11 - WpfThomas LevesqueView Answer on Stackoverflow
Solution 12 - WpfsourcenouveauView Answer on Stackoverflow
Solution 13 - WpfBryan AndersonView Answer on Stackoverflow
Solution 14 - WpfSergey AldoukhovView Answer on Stackoverflow
Solution 15 - WpfSauronView Answer on Stackoverflow
Solution 16 - WpfaweView Answer on Stackoverflow
Solution 17 - WpfSauronView Answer on Stackoverflow
Solution 18 - WpfSauronView Answer on Stackoverflow
Solution 19 - WpfSauronView Answer on Stackoverflow
Solution 20 - WpfSeeSharpView Answer on Stackoverflow
Solution 21 - WpfSauronView Answer on Stackoverflow
Solution 22 - WpfSauronView Answer on Stackoverflow
Solution 23 - WpfcplottsView Answer on Stackoverflow
Solution 24 - WpfSauronView Answer on Stackoverflow
Solution 25 - Wpfuser604613View Answer on Stackoverflow