For example, I have a pretty simple custom control called LabeledTextBox that inherits from TextBox. It's just a TextBox with a watermark in it that has had its styling stripped down to a minimal appearance. I want to make it the base class for all of the other textboxes in my app.
I have another control, SearchTextBox, which inherits from that. It is quite similar, but has some controls on the right side and some triggers for the functionality of a typical search box:
Already I have a problem, because SearchTextBox has no label in the UI. If I replace the ScrollViewer with a LabeledTextBox and make it BasedOn="{StaticResource {x:Type ui:LabeledTextBox}}"
, that works, but only if I hook up with the Text property in SearchTextBox:
public override void OnApplyTemplate()
{
LabeledTextBox ltb = GetTemplateChild("PART_LabeledTextBox") as LabeledTextBox;
Binding binding = new Binding("Text")
{
Source = this,
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
ltb.SetBinding(LabeledTextBox.TextProperty, binding);
base.OnApplyTemplate();
}
So obviously, I am missing something here... Since it is based on LabeledTextBox, why doesn't SearchTextBox have a label by default in the UI (even though it does have the label property)? Or are you not meant to inherit styles like this?
I also notice that if I create a custom control that inherits from LabeledTextBox and whose style is empty (<Style TargetType="{x:Type ui:Test}" BasedOn="{StaticResource {x:Type ui:LabeledTextBox}}" />
), then it looks just like a LabeledTextBox... So shouldn't there be something I can put in the template that basically says, "put everything from LabeledTextBox here, then add some extra stuff defined afterward," just like in normal class inheritance?
Relevant XAML:
LabeledTextBox in Generic.XAML:
<Style TargetType="{x:Type ui:LabeledTextBox}">
<Setter Property="BorderBrush" Value="{StaticResource MutedColorBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="LabelText" Value="Label text..." />
<Setter Property="LabelTextColor" Value="{StaticResource MutedColorBrush}" />
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ui:LabeledTextBox}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label x:Name="PART_Label"
Grid.Column="0"
Foreground="{TemplateBinding LabelTextColor}"
Content="{TemplateBinding LabelText}"
Padding="0"
Margin="0"
FontStyle="Italic"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center"
Visibility="Hidden"/>
<ScrollViewer x:Name="PART_ContentHost" Grid.Column="0"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center"
Margin="0" Padding="0"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
<Condition Property="IsFocused" Value="False" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Label" Property="Visibility" Value="Visible" />
<Setter TargetName="PART_ContentHost" Property="Visibility" Value="Hidden" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
SearchTextBox in Generic.XAML:
<Style TargetType="{x:Type ui:SearchTextBox}" BasedOn="{StaticResource {x:Type ui:LabeledTextBox}}">
<Setter Property="AllowDrop" Value="True" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="BorderBrush" Value="{StaticResource MutedColorBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="LabelText" Value="Search for..." />
<Setter Property="LabelTextColor" Value="{StaticResource MutedColorBrush}" />
<Setter Property="Padding" Value="1" />
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter Property="Source" Value="search.png" />
<Setter Property="ButtonSource" Value="searchx-black.png" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ui:SearchTextBox}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActualHeight}" />
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="PART_ContentHost" Grid.Column="0"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center"
Margin="0" Padding="0"/>
<Image x:Name="PART_Image" Grid.Column="1"
Source="{TemplateBinding Source}"
Visibility="Hidden"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Width="15" Height="15" />
<ui:SquareButton x:Name="PART_Button" Grid.Column="1" Width="15" Height="15" ImageHeight="10" ImageWidth="10" Padding="0" Focusable="False" Source="{TemplateBinding ButtonSource}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Text" Value="">
<Setter TargetName="PART_Image" Property="Visibility" Value="Visible" />
<Setter TargetName="PART_Button" Property="Visibility" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>