Reputation: 19122
I am experimenting with derived custom controls, and I created what I thought would be the simplest possible derivation:
I created a custom control project in VS 2010 and changed the base class for CustomControl1 from Control
to Calendar
.
Then I went into Generic.xaml and removed the default Style created for CustomControl1.
Finally I created a WPF app to consume the control.
When I add the custom control to the app's MainWindow, I had expected to see a regular WPF calendar, since I had derived from Calendar
and made no changes to the Calendar control templates.
Instead, nothing shows up at design time or run time. MainWindow remains empty. I am not sure what is going on, but it is pretty obvious that I have made a faulty assumption somewhere along the line.
Can anyone clear this up for me? Thanks for your help.
BTW--why am I doing this? I am extending the Calendar control, but I will only need to modify the CalendarDayButton control template. Before I get to my modifications, I figure I should be able to display the unmodified Calendar first. Like I said, I think I'm making a faulty assumption somewhere.
CustomControl1.cs Here is the code for CustomControl1:
using System.Windows;
using System.Windows.Controls;
namespace WpfCustomControlLibrary1
{
public class CustomControl1 : Calendar
{
static CustomControl1()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
}
}
}
Generic.xaml Here is the markup for Generic.xaml, which is located in the control's Themes folder:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomControlLibrary1">
</ResourceDictionary>
MainWindow Finally, here is the MainWindow.xaml markup:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfCustomControlLibrary1="clr-namespace:WpfCustomControlLibrary1;assembly=WpfCustomControlLibrary1" Title="MainWindow" Height="350" Width="525">
<Grid>
<WpfCustomControlLibrary1:CustomControl1 />
</Grid>
</Window>
WpfApplication1 contains a reference to the WpfCustomControlLibrary1 project.
Upvotes: 1
Views: 2715
Reputation: 5552
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
->What this line says is that CustomControl1 has its default style defined in Generic.xaml
Then I went into Generic.xaml and removed the default Style created for CustomControl1.
-> What this does is remove the default style for CustomControl1
So your control has no style so it shows nothing :D
Rather than removing the style from generic.xaml, you should copy the the style of the Calender control and change TargetType to CustomControl1 or create a new style and add BasedOn Calender
Edit to add a little more info to David's answer below for people having a look down the road
<Style TargetType="{x:Type local:FsCalendar}" BasedOn={x:Type Calender}>
<Setter Property="CalendarDayButtonStyle" Value="{StaticResource FsCalendarDayButtonStyle}" />
</Style>
This is all you need in the style. BasedOn will take care of copying everything from the default style and it will also take care of different themes. If you copy the style from the default theme of calender you will break the look for all the themes except for the one from which you copied the 'default' style.
Upvotes: 4
Reputation: 19122
BTW, I have since discovered the Style.BasedOn property, which will let you derive a style from an existing style without having to repeat the base style. There is a good blog post on it here.
Upvotes: 0
Reputation: 19122
I found my answer--thanks to NVM for all the help! This applies to controls generally, but it applies particularly to the Calendar control. If you are going to modify only part of the control, you don't have to include all of the constituent control templates.
But you do have to include the main control template, which you point to your custom control, and you have to establish a chain from the main control to the template you want to modify. In the case of my Calendar control, I need to modify only the CalendarDayButton
template to implement the changes I want to make. So, here is what I did:
I included the main Calendar template, and point that toward my custom control.
Then, to get down to the CalendarDayButton, I added a property setter to point my main Calendar style's CalendarDayButtonStyle
property to my custom CalendarDayButton style.
Here is what the main Calendar style declaration in my Generic.xaml file ends up looking like:
<!-- Calendar Style -->
<Style TargetType="{x:Type local:FsCalendar}">
<Setter Property="CalendarDayButtonStyle" Value="{StaticResource FsCalendarDayButtonStyle}" />
...
</Style>
The remainder of the main Calendar style is unchanged--it is a copy of the default style.
BTW, the CalendarDayButton style definition must appear before the main Calendar style definition in Generic.xaml, or the main Calendar style won't be able to find it.
I have written a Code Project Article titled Extending the WPF Calendar Control. It walks through the step involved in extending a complex control like the WPF Calendar. Hopefully, it will help others who are grappling with the same issues.
Upvotes: 1