123

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........
Brad Larson
  • 168,330
  • 45
  • 388
  • 563
Sauron
  • 15,788
  • 40
  • 119
  • 171
  • 7
    Have a look here http://msdn.microsoft.com/en-us/library/system.windows.controls.gridviewcolumnheader_events.aspx . The click event is inherited from ButtonBase. What you are describing are attached Events, a pretty powerfull concept in WPF (http://msdn.microsoft.com/en-us/library/bb613550.aspx). This way you can do with 100 buttons on a grid and only 1 handler. – Sorskoot Jul 14 '09 at 11:48
  • 1
    At first I was like "oh, here we go again," but then I learned something in the responses so I take it all back :o :o – Sam Harwell Jul 22 '09 at 11:11
  • 1
    should be community wiki – tsilb Sep 07 '09 at 07:22
  • 2
    @tsilb I don't think it should be community wiki, have look at this link http://meta.stackexchange.com/questions/392/should-the-community-wiki-police-be-shut-down – Prashant Cholachagudda Sep 07 '09 at 12:29

25 Answers25

87

Multibinding (combined with StringFormat):

<TextBlock>
  <TextBlock.Text>
    <MultiBinding StringFormat="{}{0}, {1}">
      <Binding Path="LastName" />
      <Binding Path="FirstName" />
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>
Julien Poulin
  • 11,837
  • 9
  • 49
  • 74
  • 1
    awesome :-) unless you're using silverlight 4 or earlier. fingers crossed for v5 – Simon_Weaver Aug 11 '10 at 03:45
  • 5
    This is great, but I'd be tempted NOT to do it. If I need to build a string, I'd class that as logic and would want to unit test the output. Stuff like this is sometimes better off in the view model as a string.Format(). – Iain Holder Aug 08 '11 at 08:00
58

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 
idursun
  • 6,120
  • 1
  • 35
  • 49
  • 4
    In VisualStudio 2010 you need to set the level of the trace settings to warning! See http://stackoverflow.com/questions/2802662/any-reason-why-presentationtracesources-tracelevelhigh-would-not-print-any-info/3004469#3004469 – WaltiD Jul 15 '10 at 11:11
44

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

<TextBox Text="{Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}" />
Sauron
  • 15,788
  • 40
  • 119
  • 171
Bryan Anderson
  • 15,383
  • 7
  • 66
  • 81
  • I can't put into words just how much I love that feature. I hated having tons of value converters laying around. – Rob Jul 14 '09 at 13:53
  • Yeah, easily one of the most time saving features added. Especially when combined with TargetNullValue a lot of problems go away. – Bryan Anderson Jul 14 '09 at 14:03
  • 6
    Putting single quotes around the StringFormat should remove some compiler warnings - `Text={Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}"` – Ryan Versaw Jul 14 '09 at 14:21
  • Good to know, I've gotten used to just ignoring them. – Bryan Anderson Jul 14 '09 at 14:30
  • Can someone give an example of this that follows internationalization recommendations? I'm pretty sure date formats shouldn't be hard coded like that. – chillitom Mar 16 '10 at 16:31
  • 1
    I was trying to convey that any arbitrary formatting string will work. I believe the internationalized version would be StringFormat='{}{0:d}' in this case. – Bryan Anderson Mar 16 '10 at 23:22
44

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}" />
Bryan Anderson
  • 15,383
  • 7
  • 66
  • 81
29

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

Swim
  • 1,531
  • 1
  • 12
  • 18
Prashant Cholachagudda
  • 12,542
  • 20
  • 93
  • 161
  • Consider adding a tooltip in such case: http://tranxcoder.wordpress.com/2008/10/12/customizing-lookful-wpf-controls-take-2/ – surfen Dec 17 '11 at 00:28
27

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>
Sauron
  • 15,788
  • 40
  • 119
  • 171
21

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 />
Sauron
  • 15,788
  • 40
  • 119
  • 171
19

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"/> 
Sauron
  • 15,788
  • 40
  • 119
  • 171
19

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>
Sauron
  • 15,788
  • 40
  • 119
  • 171
18

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

Bryan Anderson
  • 15,383
  • 7
  • 66
  • 81
18

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)

Thomas Levesque
  • 270,447
  • 59
  • 580
  • 726
  • Is the source for `WinUtil.EnableAeroGlass` available somewhere? – Oskar Mar 18 '10 at 08:42
  • Yes, but it has changed a lot since I posted this... There are now 2 properties, EnableBlur and GlassFrameMargins. You can find the code here : http://projets.developpez.com/projects/dvp-net/repository/entry/trunk/src/Developpez.Dotnet.Windows/Util/DwmUtil.cs – Thomas Levesque Mar 18 '10 at 09:15
15

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.

M. Dudley
  • 26,519
  • 30
  • 137
  • 228
14

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.

Bryan Anderson
  • 15,383
  • 7
  • 66
  • 81
11

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>
Sergey Aldoukhov
  • 20,978
  • 14
  • 68
  • 98
10

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" />
Sauron
  • 15,788
  • 40
  • 119
  • 171
7

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>
Community
  • 1
  • 1
awe
  • 20,650
  • 5
  • 76
  • 84
7

XAML Converters

The following list shows converters developed by the WPF community to convert different formats to XAML or vice versa.

Adobe Illustrator XAML Export Plugin

Adobe Photoshop to XAML Converter

Blender XAML Export Plugin

Lightwave XAML Export Plugin

Visio XAML Export

3D Studio Max to XAML Converter

Maya to XAML Converter

Flash to XAML Converter

SVG to XAML Converter

WMF/EMF to XAML Converter

Sauron
  • 15,788
  • 40
  • 119
  • 171
6

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/> 
Sauron
  • 15,788
  • 40
  • 119
  • 171
  • This does not work if using WPF to process XAML. http://msdn.microsoft.com/en-us/library/ee792007.aspx – scobi Jun 18 '10 at 23:12
6

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" />
Sauron
  • 15,788
  • 40
  • 119
  • 171
  • It's worth noting that while `x:Reference` is a XAML 2009 language feature, there are some scenarios where it will work in compiled XAML as well. However, it doesn't work everywhere, and it may break the XAML designer view. – Mike Strobel Jul 15 '11 at 16:36
  • 1
    @MikeStrobel: It works pretty much everywhere, aaand i couldn't care less about designers breaking. – H.B. Nov 23 '11 at 01:06
6

System Colors Usage

<Border Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
SeeSharp
  • 1,643
  • 11
  • 30
  • 3
    Specifying it as a DynamicResource is important because the user can change the system colors while your application is running. – M. Dudley Jan 12 '11 at 19:09
3

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>
M. Dudley
  • 26,519
  • 30
  • 137
  • 228
Sauron
  • 15,788
  • 40
  • 119
  • 171
2

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));
Sauron
  • 15,788
  • 40
  • 119
  • 171
2

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

Community
  • 1
  • 1
cplotts
  • 13,443
  • 8
  • 53
  • 63
1

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
Sauron
  • 15,788
  • 40
  • 119
  • 171
1

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.

Community
  • 1
  • 1
UrbanEsc
  • 4,211
  • 1
  • 39
  • 67