Simple Tile Horizontally / Tile Vertically functionality in WPF

Here is the main idea: We will have a grid with three rows and three columns. The middle column/row will be used to store the GridSplitter that will allow us to resize columns/rows once we are in one of the tile modes. So basically when we are in Tile Horizontally we will span the textboxes (the same can be doen with any other control) to take all the three columns. And if we are in Tile Vertically mode we will change the columns of the controls and will Span the controls so they take all the rows.
But enough talking, lets get to work:

XAML:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition Width="3" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="3" />
        <RowDefinition/>
    </Grid.RowDefinitions>

    <TextBox x:Name="txtTextBoxTop"
             Grid.Row="0" Grid.Column="0"                
             Grid.ColumnSpan="3"
             />

    <GridSplitter x:Name="split"
                  Grid.Row="1" Grid.Column="0"
                  Grid.ColumnSpan="3"
                  HorizontalAlignment="Stretch"
                  VerticalAlignment="Stretch"
                  ResizeDirection="Rows"
                  />

    <TextBox x:Name="txtTextBoxBottom"
             Grid.Row="2" Grid.Column="0"                
             Grid.ColumnSpan="3"
             />
</Grid>

And here is the code that will change to one of the modes:

VB Code Behind:

Private Sub cmdTileHorizontally_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    Grid.SetColumn(txtTextBoxTop, 0)
    Grid.SetRow(txtTextBoxTop, 0)
    Grid.SetColumnSpan(txtTextBoxTop, 3)
    Grid.SetRowSpan(txtTextBoxTop, 1)

    Grid.SetColumn(split, 0)
    Grid.SetRow(split, 1)
    Grid.SetColumnSpan(split, 3)
    Grid.SetRowSpan(split, 1)
    split.ResizeDirection = GridResizeDirection.Rows

    Grid.SetColumn(txtTextBoxBottom, 0)
    Grid.SetRow(txtTextBoxBottom, 2)
    Grid.SetColumnSpan(txtTextBoxBottom, 3)
    Grid.SetRowSpan(txtTextBoxBottom, 1)
End Sub

Private Sub cmdTileVerically_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    Grid.SetColumn(txtTextBoxTop, 0)
    Grid.SetRow(txtTextBoxTop, 0)
    Grid.SetColumnSpan(txtTextBoxTop, 1)
    Grid.SetRowSpan(txtTextBoxTop, 3)

    Grid.SetColumn(split, 1)
    Grid.SetRow(split, 0)
    Grid.SetColumnSpan(split, 1)
    Grid.SetRowSpan(split, 3)
    split.ResizeDirection = GridResizeDirection.Columns

    Grid.SetColumn(txtTextBoxBottom, 2)
    Grid.SetRow(txtTextBoxBottom, 0)
    Grid.SetColumnSpan(txtTextBoxBottom, 1)
    Grid.SetRowSpan(txtTextBoxBottom, 3)
End Sub

It is simple as that! And as a bonus you even get resizing 🙂

Binding IsChecked property of RadioButton in WPF

If you have tried to bind the RadioButton’s IsChecked property in WPF to an object, you have most likely experienced the following problem: In OneWay bindings it works great. But if you have more than one RadioButtons binded TwoWay and you click on an unchecked one, you were expecting that the object to which the previously checked RadioButton was binded to receive the value of False. But you were wrong in your expectations. That’s because for some reasons Microsoft does not obey bindings and does not pass the False value to the DependencyProperty and instead of that they just assign the value False directly to the property, which ruins the binding.

There are many proposed solutions to this around the internet, problem with all those is that they do not work with dynamically generated controls. So since I had to find a way to make this working with dynamic controls, decided to make a wrapper of the real RadioButton which will correctly Bind in two ways. Here is the code for the wrapper:

using System;
using System.IO;
using System.Printing;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using Microsoft.Win32;

namespace Controls
{
    public class RadioButtonExtended : RadioButton
    {
        static bool m_bIsChanging = false;

        public RadioButtonExtended()
        {
            this.Checked += new RoutedEventHandler(RadioButtonExtended_Checked);
            this.Unchecked += new RoutedEventHandler(RadioButtonExtended_Unchecked);
        }

        void RadioButtonExtended_Unchecked(object sender, RoutedEventArgs e)
        {
            if (!m_bIsChanging)
                this.IsCheckedReal = false;
        }

        void RadioButtonExtended_Checked(object sender, RoutedEventArgs e)
        {
            if (!m_bIsChanging)
                this.IsCheckedReal = true;
        }

        public bool? IsCheckedReal
        {
            get { return (bool?)GetValue(IsCheckedRealProperty); }
            set
            {
                SetValue(IsCheckedRealProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for IsCheckedReal. This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsCheckedRealProperty =
        DependencyProperty.Register("IsCheckedReal", typeof(bool?), typeof(RadioButtonExtended),
        new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Journal |
        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
        IsCheckedRealChanged));

        public static void IsCheckedRealChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            m_bIsChanging = true;
            ((RadioButtonExtended)d).IsChecked = (bool)e.NewValue;
            m_bIsChanging = false;
        }
    }
}

So now all you have to do is to use the ExtendedRadioButton instead of the built-in one and bind to the IsCheckedReal property instead of the IsChecked one.
Enjoy 🙂

Having different CellEditor for different rows (Xceed WPF Grid)

Currently I needed to make an Xceed WPF Grid to have different CellEditors for one column for different rows based on a condition (in my case the condition was the content of the cell). I’ve found no info for a similar situation on Xceed’s Forums. I’ve tried using the CellContentTemplateSelector for that column but after some tests I’ve noticed that when user types in the cell for that column the template disappears. And this was unacceptable. After some brainstorming and with a small hint from Xceed Support I was able to make a solution. I’ll present it to you in this article.

This solution utilizes WPF DataTriggers. So if you are not very familiar with them please read the related articles on MSDN

CellEditor.xaml

<xcdg:CellEditor x:Key="CellEditorSelector">
    <xcdg:CellEditor.EditTemplate>
        <DataTemplate>
            <StackPanel Orientation="Vertical">
                <TextBox x:Name="txtTextBox"
                        Visibility="Visible"
                        />
                <ComboBox x:Name="lstCombo"
                        Visibility="Collapsed"
                        />
                <CheckBox x:Name="chkCheckBox"
                        Visibility="Collapsed"
                        />
            </StackPanel>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type xcdg:Cell}}
                                                , Path=Content
                                                , Mode=OneWay}"
                                                Value="txt"
                >
                    <Setter TargetName="txtTextBox" Property="Visibility" Value="Visible"/>
                    <Setter TargetName="lstCombo" Property="Visibility" Value="Collapsed"/>
                    <Setter TargetName="chkCheckBox" Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type xcdg:Cell}}
                                                , Path=Content
                                                , Mode=OneWay}"
                                                Value="lst"
                >
                    <Setter TargetName="txtTextBox" Property="Visibility" Value="Collapsed"/>
                    <Setter TargetName="lstCombo" Property="Visibility" Value="Visible"/>
                    <Setter TargetName="chkCheckBox" Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type xcdg:Cell}}
                                                , Path=Content
                                                , Mode=OneWay}"
                                                Value="chk"
                >
                    <Setter TargetName="txtTextBox" Property="Visibility" Value="Collapsed"/>
                    <Setter TargetName="lstCombo" Property="Visibility" Value="Collapsed"/>
                    <Setter TargetName="chkCheckBox" Property="Visibility" Value="Visible"/>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>

By assigning the above given CellEditor to a column of and Xceed WPF Grid it will change the editor of the cell to a TextBox if the text in the cell is “txt”, to a ComboBox if the text in the cell is “lst” and to a CheckBox if the text in the cell is “chk”. By default the TextBox will be displayed.

This is a very simple example. I’ll leave to your imagination what else you can do with a similar CellEditor. You can have very complex conditions to choose which template to show. All you have to do is encapsulate the logic in a method and bind to the method in the DataTrigger. Binding property. <

Enjoy the Power WPF!

Creating a simple CheckListBox control in WPF

With .NET Framework 3.0 Microsoft has removed one control that I’ve liked and used a lot – the CheckListBox. But on the other hand with WPF the developer can easily create his own check list control. Here is how to create one yourself.
Put a simple ListBox in your window:
XAML:

<Window x:Class="winCustomPKChooser"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CheckListBox Demo" 
        Height="300" Width="300"
    >
    <ListBox x:Name="lstCheckListBox"
             Height="185"
               />
</Window>

The trick is that we will not add simple items to the list box, but instead of that we will add check boxes. Here is a simple function which adds items to our ListBox and hooks the corresponding events for when items get checked or unchecked:

VB:

Private Sub AddItemsToListBox()
     Dim chkCheckBoxToAdd as CheckBox
     For nLoop as Integer = 1 to 10
       chkCheckBoxToAdd = New CheckBox()
       chkCheckBoxToAdd.IsChecked = False
       chkCheckBoxToAdd.Content = "Item " & nLoop.ToString() 

       AddHandler chkCheckBoxToAdd.Checked _
             , AddressOf lstColumnName_ItemCheck
       AddHandler chkCheckBoxToAdd.Unchecked _
             , AddressOf lstColumnName_ItemUncheck

       lstColumnName.Items.Add(chkCheckBoxToAdd)
     Next
End Sub

Private Sub lstColumnName_ItemCheck(ByVal sender As Object _
    , ByVal e As System.Windows.RoutedEventArgs _ 
                        )
     'Do something when an item gets checked. 
     'If you need for something the checkbox 
     'which was checked use the CType(e.OriginalSource, CheckBox).
End Sub

Private Sub lstColumnName_ItemUncheck(ByVal sender As Object _
    , ByVal e As System.Windows.RoutedEventArgs _
   )
      'Do something when an item gets unchecked. 
      'If you need for something the checkbox 
      'which was unchecked use the CType(e.OriginalSource, CheckBox).
End Sub

Enjoy your own CheckListBox!

How to obfuscate WPF assemblies using obfuscation software for .NET Framework 2.0

I’ve read many posts over the Internet which are stating that it is currently impossible to obfuscate WPF assemblies. Well this is partially true.

Here is what you can do to partially protect your .NET Framework 3.0 code:
In order your code to continue to work properly you must exclude from the obfuscation at least the names of your WPF window and user control classes. You can leave in the obfuscation the variables, methods, events, etc. declared in the codebehind unless you use some of them in your markup. If this is the case you must exclude those too.

Note that by doing this you will not obfuscate the XAML code itself, but only the codebehind. Your markup can still be viewed with some disassembly tools (for example Lutz Roeder’s .NET reflector and the BamlViewer add-in).

Developing & deploying custom user controls in WPF

In WPF the development and deployment of custom user controls is similar to the development and deployment of user controls in ASP.NET. Let say that you have made a user control named MyUserCtrl1 in your main application project. In order to use this control in a Window you must first declare a namespace for it. The easy way to do this in the Window tag. After that the use of the control is as easy as writing a tag with the namespace that you have declared in the window tag and name – the name of the control:

XAML:

<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:uc="clr-namespace:MyApplication"
Title="Window1"
>
...
<uc:MyUserCtrl1 />
...
</Window>

Where MyApplication is the namespace of your application.
Now if the user control is in another assembly (for example MyApplication.GUI.dll) you must also type the assembly name in the XML namespace declaration:

XAML:

<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:uc="clr-namespace:MyApplication.GUI;assembly=MyApplication.GUI"
Title="Window1"
>
...
<uc:MyUserCtrl1 />
...
</Window>

Note that the assembly name may be different from the namespace!

Password TextBox in WPF

In .NET Framework 3.0 (WPF) Microsoft have removed the property of a TextBox, which specifies whether the textbox is Password or Normal type. But in replacement they’ve introduced a new control named PasswordBox which is very simple and intuitive to use. Here is a simple example:

XAML:

<PasswordBox x:Name="txtPassword"
ToolTip="Password"
PasswordChar="*"
/>

By default the PasswordChar is set to the big black dot from Windows XP style logon and.
In order to detect changes in the password you must handle the PasswordChanged event:

VB Codebehind:

Private Sub txtPassword_PasswordChanged(ByVal sender As System.Object _
, ByVal e As System.Windows.RoutedEventArgs _
) Handles txtPassword.PasswordChanged
'Validate input
End Sub

An in order to retrieve the typed password you just use the Password property of the PasswordBox control:

VB Codebehind:

Public Function IsAuthenticated() as Boolean
Return txtPassword.Password <> ""
End Function