WPF Design time preprocessing issue

Right, this was irritating. I was working on a project where I had a WPF Window base class with a somewhat complex constructor content. This caused the designer to crash whenever I was trying to open it on one of my deriving windowses. The code in the constructor was not in error in anyway, it still just crashed.
Here’s a short example of how to get a similar problem and how to solve it:

public class BaseWindow : Window
{
    protected string m_TextFileContent;
 
    public BaseWindow()
    {
        using (Stream stream = Assembly.GetExecutingAssembly()
                                   .GetManifestResourceStream("test.txt"))
        {
            using (StreamReader reader = new StreamReader(stream))
            {
                m_TextFileContent = reader.ReadToEnd();
            }
        }
    }
}
 
public partial class Window1 : BaseWindow
{
    public Window1()
    {
        InitializeComponent();
        this.Title = m_TextFileContent;
    }
}
<base:BaseWindow x:Class="WpfTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:base="clr-namespace:WpfTest"
    Title="Window1" Height="300" Width="300" xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit">
    <Grid></Grid>
</base:BaseWindow>

With that code your application will not build and it will look something like this in your designer:

The designer is not working
*crash*

The reason for this is that the designer needs to be able to create an instance of your base class in design time and it can’t open and read files in that state. So, we need to check if we are in design mode or running in the base construct:

public class BaseWindow : Window
{
    protected string m_TextFileContent;
 
    public BaseWindow()
    {
        if (!DesignerProperties.GetIsInDesignMode(this))
        {
            using (Stream stream = Assembly.GetExecutingAssembly()
                                       .GetManifestResourceStream("test.txt"))
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    m_TextFileContent = reader.ReadToEnd();
                }
            }
        }
    }
}

Now, to do such a thing the constructor is stupid and shouldn’t be done, but just as an example 🙂

WPF Window inheritance: problems and problems

As I’m fairly new to WPF I’m also fairly naive and I thought that WPF would be more or less over-hyped win forms and that if you wanted to make a base window you could do it like you do it in a win forms project. In a forms project you just create a class, let it inherit from the Form class and then use it as base class.
In WPF it is a bit more tricky.

The first thing I did was to create an entire .XAML file (such as BaseWindow.xaml) with XAML code and everything and then inherit it. That gave me the following error:

Partial declarations of ‘WpfTest.SomeWindow’ must not specify different base classes

You can’t separate the XAML code which sort of makes sense, so you have to create a standard class file only as your base, let it inherit from the Window class and then inherit it in your window .cs file, such as:

public class BaseWindow : Window
{
    protected string m_ImportantField = "Important!";
 
    public BaseWindow()
    {
 
    }
}

(I’ve added a protected field so as to justify this stupid example)

Then you inherit this window instead of the base Window in your presentation:

public partial class Window1 : BaseWindow
{
    public Window1()
    {
        InitializeComponent();
        this.Title = m_ImportantField;
    }
}

Now, given this XAML in your Window1 file,:

<Window x:Class="WpfTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit">
    <Grid></Grid>
</Window>

you’ll get these errors:

Partial declarations of ‘WpfTest.Window1’ must not specify different base classes
The name ‘m_ImportantField’ does not exist in the current context

This is because only the back-end code knows about the inheritance. The XAML code will be compiled into C# code as well and if it doesn’t inherit from our BaseWindow class it will of course not compile. So, we need to update the XAML as well:

<base:BaseWindow x:Class="WpfTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:base="clr-namespace:WpfTest"
    Title="Window1" Height="300" Width="300" xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit">
    <Grid></Grid>
</base:BaseWindow>

We add a new namespace, I call it ‘base’, and add the namespace of our base class. We then change the root of the XAML document to our base class, BaseClass, instead of the standard base class Window.
It should now compile and run, almost as easy as with win forms!

WPF MonthPicker: HowTo

As I was making a WPF Gui I needed a control that would allow for a user to select only a month (and a year). There was no such control, they’d even removed the standard date picker from the WPF library!
I found the WPF Toolkit which contained a calendar control (just what I needed) and I decided to give it a shot. The calendar was perfect, it even allowed me to show only months in a year instead of days in a month. You could have it in three different modes:

The three different display modes
The different display modes

The problem was that I couldn’t find a way to get the selected date from the control without forcing the user to actually selecting a day. The way it works is that if you set DisplayMode to Year, which I did, you force the user to first select month and after that select day. I only wanted them to select month!
This could be handled by sort of locking the control via its events. This is what I did:

WPF:

<Window x:Class="WpfTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit">
    <Grid>
        <my:Calendar Margin="39,54,60,40" Name="calendar1" DisplayMode="Year" DisplayModeChanged="calendar1_DisplayModeChanged" DisplayDateChanged="calendar1_DisplayDateChanged" />
        <TextBox Height="23" Margin="38,19,60,0" Name="textBox1" VerticalAlignment="Top" />
    </Grid>
</Window>

C#:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }
 
    private void calendar1_DisplayModeChanged(object sender, Microsoft.Windows.Controls.CalendarModeChangedEventArgs e)
    {
        if (calendar1.DisplayMode != Microsoft.Windows.Controls.CalendarMode.Year)
        {
            calendar1.DisplayMode = Microsoft.Windows.Controls.CalendarMode.Year;
        }
    }
 
    private void calendar1_DisplayDateChanged(object sender, Microsoft.Windows.Controls.CalendarDateChangedEventArgs e)
    {
        if (textBox1 != null) //Because the calendar may render prior to the textbox
        {
            string year = calendar1.DisplayDate.Year.ToString();
            string month = calendar1.DisplayDate.Month.ToString();
 
            if (calendar1.DisplayDate.Month < 10)
                month = "0" + month;
 
            textBox1.Text = string.Format("{0}-{1}", year, month);
        }
    }
}

This is how it could look:

A screenshot of how it could look
A MonthPicker app!