1
votes

I have a single window wpf application and tried setting up a window-wide style to apply to all my TextBox controls. I have another style that is working as expected on the TextBlock controls, but for some reason the TextBox style only work when I use an x:Key. I'm trying to have this style be the global for all TextBox in my window.

I should note that I have tried multiple properties on my TextBox style, including border thickness, foreground, background, TextWeight, etc and nothing works unless it is keyed the style is explicitly defined for each TextBox control.

This block of code is currently in my App.xaml, but I also tested it under the Window.Resources.

<ResourceDictionary>
    <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:GraphicalNestingCalculator.ViewModel" />
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Blue"/>
    </Style>
    <Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
        <Setter Property="Background" Value="Red"/>
    </Style>
</ResourceDictionary>

And the TextBox in a stackpanel

<StackPanel Orientation="Horizontal">
            <StackPanel.Resources>
                <Style TargetType="{x:Type TextBox}">
                    <Setter Property="Margin" Value="10,0,10,0"/>
                </Style>
            </StackPanel.Resources>
            <TextBlock>Part Width:</TextBlock>
            <TextBox Name="partWidthTextBox" Text="{Binding Path=Layout.Part.Width, UpdateSourceTrigger=LostFocus}" Style="{StaticResource TextBoxStyle}" Width="50" >
            </TextBox>
            <TextBlock>Part Height:</TextBlock>
            <TextBox Name="partHeightTextBox" Text="{Binding Path=Layout.Part.Height, UpdateSourceTrigger=LostFocus}" Style="{StaticResource TextBoxStyle}" Width="50" />
        </StackPanel>
2
Where are these 2 styles defined?Yarik
This works when putting the code inside "Application.Resources" in App.xaml. All textboxes placed on any form have a red background. Please provide a complete example that doesn't work for you.NineBerry
Well, can you show us the XAML of the Textbox?NineBerry

2 Answers

2
votes

If you want the both the implicit Style without an x:Key and the style what you define in your App.xaml or <Window.Resources> to be applied you should base the former one on the latter:

<StackPanel Orientation="Horizontal">
    <StackPanel.Resources>
        <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
            <Setter Property="Margin" Value="10,0,10,0"/>
            <Setter Property="FontSize" Value="40" />
        </Style>
    </StackPanel.Resources>
    <TextBlock>Part Width:</TextBlock>
    <TextBox Name="partWidthTextBox" Text="{Binding Path=Layout.Part.Width, UpdateSourceTrigger=LostFocus}" Width="50" >
    </TextBox>
    <TextBlock>Part Height:</TextBlock>
    <TextBox Name="partHeightTextBox" Text="{Binding Path=Layout.Part.Height, UpdateSourceTrigger=LostFocus}" Width="50" />
</StackPanel>

App.xaml:

<ResourceDictionary>
    <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:GraphicalNestingCalculator.ViewModel" />
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Blue"/>
    </Style>
    <Style TargetType="{x:Type TextBox}">
        <Setter Property="Background" Value="Red"/>
    </Style>
</ResourceDictionary>

When you set Style="{StaticResource TextBoxStyle}" on the TextBox the implicit style that you define in <StackPanel.Resources> will be ignored. This is the expected behaviour.

1
votes

You have to delete the key when you define window wide resource styles, otherwise you'll need to explicitly reference it later

</Style>
<Style TargetType="TextBox">
    <Setter Property="Background" Value="Red"/>
</Style>

Edit

If you want to apply also a more specific Style, the more specific one should be based on the window wide one: BasedOn="{StaticResource {x:Type TextBox}}" (as already shown in the other answer)

Anyway, since the requirement of setting margins for the StackPanel children can be more generic than for a TextBox only, there is also another option with an attached property instead of a Style

<StackPanel Orientation="Horizontal" local:MarginSetter.Margin="10">

The last generic solution for the margins is more complicated however and - for the children of the panel to be loaded - I'd subscribe the following event

    private void StackPanel_Loaded(object sender, RoutedEventArgs e)
    {
        MarginSetter.CreateThicknesForChildren(sender, new DependencyPropertyChangedEventArgs());
    }