1

I'm looking for a way to more strongly bind the default Control Template of my custom control to the control instead of using a Style. I'll show my simplest example here to explain the need:

 public class UnitTextBox : TextBox { public string UnitLabel {...} public static readonly DependencyProperty UnitLabelProperty = DependencyProperty.Register("UnitLabel", typeof(string), typeof(UnitTextBox), new PropertyMetadata("")); } 

This control just adds an extra string property for a unit label (like millimeters), given the following simple control template derived from TextBox, it puts a unit label within the text box to keep things nice and clean and properly dimensioned:

 <ControlTemplate x:Key="UnitTextBoxTemplate" TargetType="{x:Type local:UnitTextBox}"> <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> <DockPanel> <TextBlock DockPanel.Dock="Right" Text="{TemplateBinding UnitLabel}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="8,0,2,0" Focusable="False" IsHitTestVisible="False" Background="Transparent" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" FontStyle="{TemplateBinding FontStyle}" /> <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/> </DockPanel> </Border> ...(triggers) </ControlTemplate> 

All of that works wonderfully, however this control is basically still a TextBox, and I have lots of styles for TextBoxes already that I use, so I don't want to use a default style to apply the template:

 <Style TargetType="{x:Type local:UnitTextBox}"> <Setter Property="Template" Value="{DynamicResource UnitTextBoxTemplate}"/> </Style> 

Doing the above means that I can't use my RegularTextBox style which works just fine for my UnitTextBox. So instead, every time I wish to add a UnitTextBox I must explicitly specify the template that makes it function properly:

 <ctrl:UnitTextBox Template="{DynamicResource UnitTextBoxTemplate}" UnitLabel="mm/min" Style="{StaticResource RegularTextBox}"/> 

I've been working with WPF for ages, but I do relatively few custom controls, and have suffered with they Default Style method when I do, but I'm thinking there must be a better way, but google-fu has failed me time and again.

I'm hoping there is some way to assign the template in the constructor/Init routine of UnitTextBox, but I'm struggling to reach the resource dictionary from code; so I'm wondering if there's a more esoteric way to do this.

6
  • Can't you simply base the default style on the existing style and just set the Template property? <Style TargetType="{x:Type local:UnitTextBox}" BasedOn="{StaticResource RegularTextBox}">...</Style>. What's the problem with this approach? Commented Oct 17, 2019 at 13:20
  • You can, but then you have to multiply the number of TextBox styles you have by the number of TextBox derivatives. Which I expect will yield a mess in short order since I have a few other similar cases. That's my grudging solution, but it seems there should be something elegant, right? Commented Oct 17, 2019 at 13:23
  • I don't think I understand the issue. If you want another style than the default one, just set the Style property of that particular element. "I'm hoping there is some way to assign the template in the constructor/Init routine of UnitTextBox". How would this help? Commented Oct 17, 2019 at 13:25
  • The core function of the UnitTextBox control (adding a TextBlock inside a TextBox) is bound up in the default style, if I have 5 different TextBox styles, using these styles on the UnitTextBox works fine, except it overrides the default style, which provides the template. So I have to explicitly assign the template, or I have to create a style based on each of the 5 styles, add a setter for Template and use that. It works, but it sucks. Setting a template in the init means it has the Template already assigned if the style fails to do so. Commented Oct 17, 2019 at 13:28
  • You may handle the Loaded and set the Template property in the event handler. Commented Oct 17, 2019 at 13:37

1 Answer 1

1

If you don't want to define a default Style, you may handle the Loaded event in your control class and set the Template property in the event handler.

public UnitTextBox() : base() { this.Loaded += UnitTextBox_Loaded; } private void UnitTextBox_Loaded(object sender, RoutedEventArgs e) { var res = this.FindResource("UnitTextBoxTemplate"); this.Template = res as ControlTemplate; } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.