WPF
Introductory material is on MSDN
Resources
You can reference .net static classes by adding the xaml namespace (eg xmlns:local="clr-namespace:WpfApplication1") and using {x:Static ...}.
Binding to changing properties like SystemColors and other dependency properties requires {DynamicResouce {x:Static MyKey }}. Ugh.
<TextBlock Text="{x:Static local:StaticSettings.ConnectionString}"/>
A StaticResource is a dictionary with an x:Key. They can be defined anywhere up the hierarchy to Application, as long as they are before the reference. In code, you can use TryFindResource("x").
NB: a DynamicResource can redefine the dictionary item.
<UserControl.Resources>
<SolidColorBrush x:Key="StandardBackground" Color="AliceBlue"/>
</UserControl.Resources>
<StackPanel>
<Button x:Name="theButton" Content="Click Me" Background="{StaticResource StandardBackground}" />
</StackPanel>
ResourceDictionary
You can (and often should) move resources into one or ResourceDictionary xaml files. You then have to reference them- if you have several sources, in a MergedDictionary. It's ugly.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- you can merge in external dictionaries -->
<ResourceDictionary Source="Dictionary1.xaml" />
<!-- and add local resources -->
<ResourceDictionary>
<SolidColorBrush x:Key="StandardBackground" Color="AliceBlue"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Style
You can also add a Style with Setters (probably with a TargetType). Controls reference it through Style="{StaticResource StyleName}" (if there is no x:Key it applies to all controls of that type).
<UserControl.Resources>
<Style x:Key="StandardButton" TargetType="Button">
<Setter Property="Background" Value="AliceBlue"/>
</Style>
</UserControl.Resources>
<StackPanel>
<Button x:Name="theButton" Content="Click Me" Style="{StaticResource StandardButton}" />
<TextBlock Text="{x:Static local:StaticSettings.ConnectionString}"
</StackPanel>
Styles can be BasedOn previous styles: BasedOn="{StaticResource StandardButton}"
Binding
MSDN
Simple binding between WPF elements with ElementName:
<TextBox Name="textBox1">Hello</TextBox>
<Label Name="label1" Content="{Binding ElementName=textBox1, Path=Text}" />
Otherwise use Source, or set the DataContext on the element or container.
Controls that display collections (like ListBox) have an ItemSource (bind to collection object) and a DisplayMemberPath (property to display).
<UserControl x:Class="WpfApplication1.UserControl3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfApplication1="clr-namespace:WpfApplication1">
<Grid>
<Grid.Resources>
<ObjectDataProvider x:Key="odpKey"
ObjectType="{x:Type WpfApplication1:DataLoader}"
MethodName="GetUsers"/>
</Grid.Resources>
<ListView ItemsSource="{Binding Source={StaticResource odpKey}}" DisplayMemberPath="Name" />
</Grid>
</UserControl>
DataTemplate
Use a DataTemplate to display a richer view of the items (in control.Content or itemcontrol.ItemTemplate).
DataTemplates can be resources, and can have a DataType.
Formatting: Binding has a StringFormat={}{0} items, (you have to use the {} escaping at the start) - it only works on controls with string Text
Content controls have ContentStringFormat, list controls have ItemStringFormat.
For more complex conversions, implement IValueConverter, hook it up as a resource, and add , Converter={StaticResource myConverter
<ListView ItemsSource="{Binding Source={StaticResource odpKey}}">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Path=Name}" MinWidth="60" />
<TextBlock Text="{Binding Path=Birthday, StringFormat='dd/MM/yyyy'}" />
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Debugging binding
You can debug individual bindings (from 3.5) by referencing xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase" and appending ", diagnostics:PresentationTraceSources.TraceLevel=High" to the path.
<UserControl x:Class="WpfApplication1.UserControl4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase">
<Grid>
<Grid.Resources>
<local:DataSettings x:Key="myDataSource" />
</Grid.Resources>
<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=ConnectionString, diagnostics:PresentationTraceSources.TraceLevel=High}"/>
</Grid>
</UserControl>
Master-detail item controls
Master-details can be tied if the controls bind to the same collection and item controls have IsSynchronizedWithCurrentItem=true
<ListView ItemsSource="{Binding Source={StaticResource odpKey}}"
IsSynchronizedWithCurrentItem="True">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Path=Name}" MinWidth="60" />
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Label Content="{Binding Source={StaticResource odpKey}, Path=Description}" />
Commands
Rather than do a Winforms like event...
<Button Content="Click Me" Click="Button_Click" />
private void Button_Click(object sender, RoutedEventArgs e)
{
var d = new OpenFileDialog();
d.ShowDialog();
}
Controls like button have a Command property (and commands can also have gestures/keys attached).
If it's not a built in command (ApplicationCommands.Paste), a command needs a handler method (think event, like above), which is linked to the command by a commandBinding.
CommandBindings bubble up - the control checks it's bindings for a handler, then works up to Window to find a binding that gives it a handler. If there is no binding - the control is disabled.
- Custom commands are static classes with a static Routed[UI]Command getter, which is what the control "Command=" points to.
- Remember to add the xmlns:local="clr:namespace:..." to the command class namespace
- The Execute command handler has a (object sender, ExecutedRoutedEventArgs e) signature. Set e.IsHandled = true to stop bubbling.
- Optionally add the CanExecute command handler.
- Add the command binding to the control or a container that hooks the command to the handler.
public static class MyCommands
{
public static RoutedCommand Hello = new RoutedCommand("Hello", typeof(MyCommands));
public static void HelloExecuted(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Hello!");
e.Handled = true; //stop bubbling
}
}
<UserControl x:Class="WpfApplication1.UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Commands="clr-namespace:WpfApplication1.Commands">
<UserControl.CommandBindings>
<!-- command points to Executed/ CanExecute methods.
built-in commands (ApplicationCommands.Help) don't
need x:Static binding-->
<CommandBinding
Command="{x:Static Commands:MyCommands.Hello}"
Executed="HelloExecuted" />
</UserControl.CommandBindings>
<StackPanel>
<!-- assign command -->
<Button Content="Click Me"
Command="Commands:MyCommands.Hello" />
</StackPanel>
</UserControl>