DerpyNerd
DerpyNerd

Reputation: 4813

WPF UserControl: Client-side validation of TargetType for custom styles?

I have a UserControl for multi-purpose use. For the sake of simplicity, I'll show you the control first:

<UserControl x:Class="CompetitionAgent.View.UserControls.ExpandingButtonGrid"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" d:DesignWidth="200" d:DesignHeight="200"
             Margin="0" Padding="0" Width="Auto" Height="Auto" >
    <StackPanel Name="stpBody" Style="{Binding Style}">
        <Button x:Name="btnExpander" Content="{Binding ExpanderButtonText}"
                Style="{Binding ExpandButtonStyle}"
                HorizontalAlignment="Center" Click="btnExpander_Click"
                Height="25" Width="Auto" />
        <StackPanel x:Name="stpButtons" Orientation="Horizontal" 
                    Style="{Binding PanelStyle}"
                    Margin="0">
        </StackPanel>
    </StackPanel>
</UserControl>

Controls stpBody, stpButtons and btnExpander all have styles bound by the DataContext. The fields look like this:

#region body styles
public Style Style { get; set; }
public Style ExpandButtonStyle { get; set; }
#endregion body styles

#region button pannel styles
public Style PanelStyle { get; set; }
public Style ButtonStyle { get; set; }
#endregion button pannel styles 

So when this UserControl is used in another window, it would look somewhat like this:

<UserControls:ExpandingButtonGrid x:Name="ebgSchemeManager" 
                                  Style="{StaticResource ExpandingButtonGridStyle}" 
                                  PanelStyle="{StaticResource ExpandingButtonGridPanelStyle}" 
                                  ExpandButtonStyle="{StaticResource ExpandingButtonGridExpandButtonStyle}" />

I was wondering, is there a way to validate the TargetTypes of the StaticResource styles so that they are required to target a stackpanel or button respectively?

For example, style ExpandingButtonGridExpandButtonStyle could target a DockPanel, resulting in a XAML parse exception at runtime.

UPDATE - Summary and update on Depency Objects

I've just figured out what DepencyObjects are (hurray!). For those who are wondering, you need to register the field so the property can be assigned to dynamically.

public static readonly DependencyProperty ExpandButtonStyleProperty =
    DependencyProperty.Register("ExpandButtonStyle", typeof(Style), typeof(ExpandingButtonPanel));

public Style ExpandButtonStyle
{
    get
    {
        return (Style)GetValue(ExpandButtonStyleProperty);
    }
    set
    {
        if (!typeof(Button).IsAssignableFrom(value.TargetType))
        {
            throw new ArgumentException("The target type is expected to be button");
        }
        SetValue(ExpandButtonStyleProperty, value);
    }
}

Upvotes: 1

Views: 66

Answers (1)

Nitram
Nitram

Reputation: 6716

Sure there is. You can verify the Style.TargetType in your setter. This will also be checked by the WPF Designer.

For example:

private Style _buttonStyle;
public Style ButtonStyle 
{ 
    get 
    {
        return _buttonStyle;
    }
    set 
    { 
        if (!typeof(Button).IsAssignableFrom(value.TargetType))
        {
            throw new ArgumentException("The target type is expected to be Button");
        } 
        _buttonStyle = value;
    } 
}

Upvotes: 1

Related Questions