Home > Software engineering >  Is there a clean way to replace a common control (e.g. CheckBox) with a custom descendant?
Is there a clean way to replace a common control (e.g. CheckBox) with a custom descendant?

Time:01-03

I have created custom replacements for several built-in controls, such as CheckBox and RadioButton. These are not just new templates/styles for the existing controls but new descendant classes that provide some additional functionality (but no new properties). I'm now wondering whether I will have to go through all my views and replace all instances of <CheckBox ... /> with <controls:MyCheckBox ... /> and add the relevant namespace where necessary or whether there is an easier way.

I guess I could do something like the following:

<Style TargetType="{x:Type CheckBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
                <controls:MyCheckBox Width="{TemplateBinding Width}"
                                     Height="{TemplateBinding Height}"
                                     Content="{TemplateBinding Content}"
                                     IsChecked="{TemplateBinding IsChecked}"
                                     and so on... />
            <ControlTemplate />
        </Setter.Value>
    </Setter>
</Style>

...but that feels kinda hacky... Is there a cleaner way to do this?

CodePudding user response:

You can neaten up the templating somewhat.

Say I have a MyCheckBox which inherits from checkbox.

I can make it use the checkbox template:

    public class MyCheckBox : CheckBox
    {
        static MyCheckBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCheckBox), new FrameworkPropertyMetadata(typeof(CheckBox)));
        }
    }

Then when I use MyCheckBox it will look very much like a checkbox. This works because every control has a default style which sets it's template. That default style uses the type of the control as a key and hence x:Type CheckBox is the key of the checkbox style.

That doesn't get round an xmlns reference to your custom control library.

        xmlns:cc="clr-namespace:WpfCustomControlLibrary1;assembly=WpfCustomControlLibrary1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <cc:MyCheckBox/>
    </Grid>

I think there is a rather dirty way you could use to avoid declaring an xmlns.

The wpf controls are referenced by the line

 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

You can tell the compiler your controls are part of that.

https://learn.microsoft.com/en-us/dotnet/api/system.windows.markup.xmlnsdefinitionattribute?view=windowsdesktop-7.0

https://paulstovell.com/xmlnsdefinition/

I would not recommend this though and maybe you could just do a replace all to change your controls.

CodePudding user response:

I'm now wondering whether I will have to go through all my views and replace all instances of <CheckBox ... /> with <controls:MyCheckBox ... /> and add the relevant namespace where necessary or whether there is an easier way.

Find and replace all occurances of <CheckBox ... with <controls:MyCheckBox ... across all of your XAML markup files is probably the easiest and most correct solution to replace the built-in control with your custom one.

Replace all is the cleaner and easiest way of doing this. Press CTRL> H in Visual Studio and select Current Project and then compare the modifed files.

  • Related