In dependency property pattern in WPF, automatically cast the result of GetValue() to expected return type

1 day ago 2
ARTICLE AD BOX

WPF is quite dated so I doubt they're are better snippets to speed up handling properties of custom controls aside from: propdp or propa. Of course, I'm open to getting corrected on this.

I think your approach to the problem can be improved. There's no need to create a new control each time you want to change behavior. Use ContentControl, AttachedProperties or Microsoft.Xaml.Behaviors where you can.

In this case, you can create a custom control and nest whatever you want in.

public class LabelHost : ContentControl { public string Label { get { return (string)GetValue(LabelProperty); } set { SetValue(LabelProperty, value); } } public static readonly DependencyProperty LabelProperty = DependencyProperty.Register("Label", typeof(string), typeof(LabelHost), new PropertyMetadata("")); public HorizontalAlignment Alignment { get { return (HorizontalAlignment)GetValue(AlignmentProperty); } set { SetValue(AlignmentProperty, value); } } public static readonly DependencyProperty AlignmentProperty = DependencyProperty.Register("Alignment", typeof(HorizontalAlignment), typeof(LabelHost), new PropertyMetadata(HorizontalAlignment.Center)); }

Your style declaration could look like this:

<!--#region LabelHost--> <ControlTemplate x:Key="LabelHostTemplate" TargetType="{x:Type ui:LabelHost}"> <Grid Background="Transparent"> <DockPanel> <ContentPresenter x:Name="PART_Presenter" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Content="{TemplateBinding ContentControl.Content}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" DockPanel.Dock="Bottom" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" /> <Label HorizontalAlignment="{TemplateBinding Alignment}" Content="{TemplateBinding Label}" /> </DockPanel> </Grid> </ControlTemplate> <Style TargetType="{x:Type ui:LabelHost}"> <Setter Property="Template" Value="{StaticResource LabelHostTemplate}" /> </Style> <!--#endregion-->

You could then use it like this:

<StackPanel> <ui:LabelHost Alignment="Right"> <TextBox /> </ui:LabelHost> <ui:LabelHost Alignment="Left"> <Button /> </ui:LabelHost> </StackPanel>

If you'd still rather have your controls specifically defined, you could do something like this:

public class LabelTextBox : LabelHost { public LabelTextBox() { Content = new TextBox(); } } public class LabelTextBox2 : Border { private LabelHost _host; private TextBox _box; public LabelTextBox2() { _host = new LabelHost(); _box = new TextBox(); _host.Content = _box; _box.TextChanged += (s, e) => { // Custom code here... }; } }

To deal with more complex logic, just check the Content property and adapt accordingly.

public class LabelHost : ContentControl { // ... public string TextContent { get { return (string)GetValue(TextContentProperty); } set { SetValue(TextContentProperty, value); } } public static readonly DependencyProperty TextContentProperty = DependencyProperty.Register("TextContent", typeof(string), typeof(LabelHost), new PropertyMetadata("", HandleText)); private static void HandleText(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is not LabelHost host) return; if (host.Content is TextBox textBox) { if (e.NewValue is string txt) textBox.Text = txt; // You can also just use Binding instead... } } }

Of course you're free to create partial declarations of the class if you really really need it to be a large control without code clutter.

LabelHost.cs LabelHost.TextBox.cs LabelHost.Button.cs ...etc
Read Entire Article