Wednesday, 16 November 2011

WPF TextBlock Control

How to change the line height within a TextBlock

To change the line hight within a TextBlock, you have to set the LineHeight to the desired height (in logical units) and also the LineStackingStrategy to BlockLineHeight, because otherwhise you will not see any effect.
 
<TextBlock Text="This is a 
multiline text." 
           LineHeight="25" LineStackingStrategy="BlockLineHeight" />

WPF ListView Control

How to Hide the Header of a ListView

To hide the header of a ListView you can modify the Visibility property of the ColumnHeaderContainer by overriding the style locally.
<ListView>
    <ListView.View>
        <GridView>
            <GridView.ColumnHeaderContainerStyle>
               <Style>
                   <Setter Property="FrameworkElement.Visibility" Value="Collapsed"/>
               </Style>
            </GridView.ColumnHeaderContainerStyle>
            <GridView.Columns>
                ...
            </GridView.Columns>
        </GridView>
    </ListView.View>
</ListView>
 

WPF ListBox Control

Introduction

The ListBox control displays a list of items. The user can select one or multiple items depending on the selection mode. The typical usage of a listbox in WPF is to bind its items to a list of business objects and display them by applying a data template.

 
<ListBox Margin="20">
    <ListBoxItem>New York</ListBoxItem>
    <ListBoxItem>Los Angeles</ListBoxItem>
    <ListBoxItem>Paris</ListBoxItem>
    <ListBoxItem>Zürich</ListBoxItem>
</ListBox>
 
 

How to define a Trigger for IsSelected in the DataTemplate

If you want to change the appearance of a ListBoxItem when it is selected, you have to bind the IsSelected property of the ListBoxItem. But this is a bit tricky, you have to use a relative source with FindAcestor to navigate up the visual tree until you reach the ListBoxItem.
 
<DataTemplate x:Key="myDataTemplate">
    <Border x:Name="border" Height="50">
        <TextBlock Text="{Binding Text}" />
    </Border>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding RelativeSource=
            {RelativeSource Mode=FindAncestor, AncestorType=
                {x:Type ListBoxItem}},Path=IsSelected}" Value="True">
            <Setter TargetName="border" Property="Height" Value="100"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>
 
 

More articles about the ListBox

Apply a DataTemplate
Strech an Item
Selected Item Background
Layout of Items


Radio Button

Introduction

The RadioButton control has its name from old analog radios which had a number of programmable station buttons. When you pushed one in, the previosly selected poped out. So only one station can be selected at a time.
The RadioButton control has the same behavior. It lets the user choose one option out of a few. It the list of options gets longer, you should prefer a combo or list box instead.
To define which RadioButtons belong togehter, you have to set the GroupName to the same name.
To preselect one option set the IsChecked property to True.

 
<StackPanel>
    <RadioButton GroupName="Os" Content="Windows XP" IsChecked="True"/>
    <RadioButton GroupName="Os" Content="Windows Vista" />
    <RadioButton GroupName="Os" Content="Windows 7" />
    <RadioButton GroupName="Office" Content="Microsoft Office 2007" IsChecked="True"/>
    <RadioButton GroupName="Office" Content="Microsoft Office 2003"/>
    <RadioButton GroupName="Office" Content="Open Office"/>
</StackPanel>
 
 

How to DataBind Radio Buttons in WPF

The radio button control has a known issue with data binding. If you bind the IsChecked property to a boolean and check the RadioButton, the value gets True. But when you check another RadioButton, the databound value still remains true.
The reason for this is, that the Binding gets lost during the unchecking, because the controls internally calls ClearValue() on the dependency property.
 
<Window.Resources>
   <EnumMatchToBooleanConverter x:Key="enumConverter" />
</Window.Resources>
 
 
<RadioButton Content="Option 1" GroupName="Options1" 
             IsChecked="{Binding Path=CurrentOption, Mode=TwoWay, 
                                 Converter={StaticResource enumConverter},
                                 ConverterParameter=Option1}"  />
<RadioButton Content="Option 2" GroupName="Options2" 
             IsChecked="{Binding Path=CurrentOption, Mode=TwoWay, 
                                 Converter={StaticResource enumConverter},
                                 ConverterParameter=Option2}"  />
<RadioButton Content="Option 3" GroupName="Options3" 
             IsChecked="{Binding Path=CurrentOption, Mode=TwoWay, 
                                 Converter={StaticResource enumConverter},
                                 ConverterParameter=Option3}"  />
 
 
 
public class EnumMatchToBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, 
                              object parameter, CultureInfo culture)
        {
            if (value == null || parameter == null)
                return false;
 
            string checkValue = value.ToString();
            string targetValue = parameter.ToString();
            return checkValue.Equals(targetValue, 
                     StringComparison.InvariantCultureIgnoreCase);
        }
 
        public object ConvertBack(object value, Type targetType, 
                                  object parameter, CultureInfo culture)
        {
            if (value == null || parameter == null)
                return null;
 
            bool useValue = (bool)value;
            string targetValue = parameter.ToString();
            if (useValue)
                return Enum.Parse(targetType, targetValue);
 
            return null;
        }
    }   
 
 

WPF Slider Control

How to Make a Slider Snap to Integer Values

If you just set the Minimum and Maximum of a slider and choose a value the result is determined by the pixel position of the thumb. The value is typically a high-precision value with many decimal places. To allow only integer values you have to set the IsSnapToTickEnabled property to True.
<Slider Minimum="0"
        Maximum="20"
        IsSnapToTickEnabled="True"
        TickFrequency="2"
 

Popup Control

Introduction follows...

How to make the popup close, when it loses focus

Just set the StaysOpen property to False. Unfortunately this is not the default behavior
 
<Popup StaysOpen="False" />
 

Menus in WPF

Menu

The Menu control derives from HeaderedItemsControl. It stacks it items horizontally and draws the typical gray background. The only property that the Menu adds to ItemsControl is the IsMainMenu property. This controls if the menu grabs the focus if the user presses F10 or the ALT key.
 
<Menu IsMainMenu="True">
    <MenuItem Header="_File" />
    <MenuItem Header="_Edit" />
    <MenuItem Header="_View" />
    <MenuItem Header="_Window" />
    <MenuItem Header="_Help" />
</Menu>
 
 

MenuItem

The MenuItem is a HeaderedItemsControl. The content of the Header property is the caption of the menu. The Items of a MenuItems are its sub menus. The Icon property renders a second content on the left of the caption. This is typically used to draw a little image. But it can be used for type of content.
You can define a keyboard shortcut by adding an underscore in front of a character.
 
<MenuItem Header="_Edit">
    <MenuItem Header="_Cut" Command="Cut">
        <MenuItem.Icon>
            <Image Source="Images/cut.png" />
        </MenuItem.Icon>
    </MenuItem>
    <MenuItem Header="_Copy" Command="Copy">
        <MenuItem.Icon>
            <Image Source="Images/copy.png" />
        </MenuItem.Icon>
    </MenuItem>
    <MenuItem Header="_Paste" Command="Paste">
        <MenuItem.Icon>
            <Image Source="Images/paste.png" />
        </MenuItem.Icon>
    </MenuItem>
</MenuItem>
 
 

Checkable MenuItems

You can make a menu item checkable by setting the IsCheckable property to true. The check state can be queried by the IsChecked property. To get notified when the check state changes you can add a handler to the Checked and Unchecked property.
 
<MenuItem Header="_Debug">
    <MenuItem Header="Enable Debugging" IsCheckable="True" />
</MenuItem>
 
 

Separators

Separator is a simple control to group menu items. It's rendered as a horizontal line. It can also be used in ToolBar and StatusBar.
 
<Menu>
    <MenuItem Header="_File">
        <MenuItem Header="_New..." />
        <Separator />
        <MenuItem Header="_Open..." />
        <Separator />
        <MenuItem Header="_Save" />
        <MenuItem Header="_Save As..." />
        <Separator />
        <MenuItem Header="_Exit" />
    </MenuItem>
</Menu>
 
 

Callbacks

You can register a callback to any menu item by adding a callback to the Click event.
 
<Menu>
    <MenuItem Header="_File">
        <MenuItem Header="_New..."  Click="New_Click"/>
    </MenuItem>
</Menu>
 
 
 
private void New_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("You clicked 'New...'");
}
 
 

How to bind MenuItems dynamically using MVVM

If you are using the model-view-viewmodel pattern, you probably want to define the available menu command dynamically in your code and then bind them to a MenuItem control. The following sample shows you how to do this:
 
<Menu>
    <Menu.Resources>
        <Style x:Key="ThemeMenuItemStyle" TargetType="MenuItem">
           <Setter Property="Header" Value="{Binding Name}"></Setter>
           <Setter Property="Command" Value="{Binding ActivateCommand}"/>
           <Setter Property="IsChecked" Value="{Binding IsActive}" />
           <Setter Property="IsCheckable" Value="True"/>
        </Style>
    </Menu.Resources>
    <MenuItem Header="Themes" ItemsSource="{Binding Themes}" 
              ItemContainerStyle="{StaticResource ThemeMenuItemStyle}"  />
</Menu>
 
 

Keyboard Shortcuts

To add a keyboard shortcut to a menu item, add a underscode "_" in front of the caracter you want to use as your hot key. This automatically sets the InputGestureText to an appropriate value. But you can also override the proposed text by setting this property to a text of your choice.