views:

5086

answers:

22

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........
+30  A: 

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

<TextBox Text="{Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}" />
Bryan Anderson
I can't put into words just how much I love that feature. I hated having tons of value converters laying around.
unforgiven3
Yeah, easily one of the most time saving features added. Especially when combined with TargetNullValue a lot of problems go away.
Bryan Anderson
Putting single quotes around the StringFormat should remove some compiler warnings - `Text={Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}"`
Ryan Versaw
Good to know, I've gotten used to just ignoring them.
Bryan Anderson
Will it work for Silverlight
Prashant
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
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
+57  A: 

Multibinding (combined with StringFormat):

<TextBlock>
  <TextBlock.Text>
    <MultiBinding StringFormat="{}{0}, {1}">
      <Binding Path="LastName" />
      <Binding Path="FirstName" />
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>
Julien Poulin
lol I just wish I knew about this loooong before =P
Carlo
awesome :-) unless you're using silverlight 4 or earlier. fingers crossed for v5
Simon_Weaver
+30  A: 

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
+8  A: 

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
+40  A: 

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
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
+1 for #awesome
Greg D
+14  A: 

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
Don't forget http://karlshifflett.wordpress.com/
qntmfred
+1 for humor. Nice.
cplotts
+5  A: 

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>
awe
+13  A: 

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
Is the source for `WinUtil.EnableAeroGlass` available somewhere?
Oskar
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
+18  A: 

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
Thank you! I've been wondering how to do that for years.
Jonathan Allen
+14  A: 

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

Prashant
+11  A: 

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
+4  A: 

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
This does not work if using WPF to process XAML. http://msdn.microsoft.com/en-us/library/ee792007.aspx
Scott Bilas
+10  A: 

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
+3  A: 

Support for Arbitrary Dictionary Keys

In XAML 2006 all explicit x:Key value were threated 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>
Sauron
+6  A: 

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
Target accepts just `Target="firstName"` in WPF 4.0. :)
Yogesh
+11  A: 

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
+12  A: 

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
A: 

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
+6  A: 

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
A: 

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
+3  A: 

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
+2  A: 

System Colors Usage

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