Home > Software design >  WPF trouble applying a style to a textbox
WPF trouble applying a style to a textbox

Time:12-29

I am a bit new to WPF and am in need of some assistance.. I am trying to setup a mouse over trigger event to change the 'style' of a textbox.. ie - when the user moves the mouse over the textbox, I want the border and background to change. So, after doing some digging around and reading here and there on this, I ended up with this:

<Window.Resources>
    <Style x:Key="WMCTextBoxStyle"  TargetType="{x:Type TextBox}" BasedOn="{StaticResource WMCTextBoxStyle}">
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="OverridesDefaultStyle" Value="True" />
        <Setter Property="KeyboardNavigation.TabNavigation"  Value="None" />
        <Setter Property="AllowDrop" Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBoxBase}">
                    <Border Name="Border1"
                            CornerRadius="3"
                            Padding="2"
                            BorderThickness="1"
                            Height="Auto" 
                            Width="auto" 
                            VerticalAlignment="Center" 
                            HorizontalAlignment="Center">
                        <Border.BorderBrush>
                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                <GradientStop Color="#FFA4B3C5" Offset="0"/>
                                <GradientStop Color="#FFA4B3C5" Offset="1"/>
                            </LinearGradientBrush>
                        </Border.BorderBrush>

                        <Border Name="Border2"
                            CornerRadius="0"
                            BorderThickness="1"
                            VerticalAlignment="Center" 
                            HorizontalAlignment="Center"
                            BorderBrush="Black">
                            <Border.Background>
                                <RadialGradientBrush GradientOrigin="0.225,-0.616" RadiusY="0.863" RadiusX="0.757">
                                    <GradientStop Color="#EEFFFFFF"/>
                                    <GradientStop Color="#00FFFFFF" Offset="0.696"/>
                                </RadialGradientBrush>
                            </Border.Background>
                            <ScrollViewer Margin="0" x:Name="PART_ContentHost" />
                        </Border>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Style" Value="{DynamicResource WMCTextBoxStyle}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>

        </Setter>
    </Style>
</Window.Resources>

When I try to compile, I get the following two errors:

Error XDG0062 '{DependencyProperty.UnsetValue}' is not a valid value for the 'System.Windows.Controls.Control.Template' property on a Setter." in Line:12

Error XDG0062 Style object is not allowed to affect the Style property of the object to which it applies. in Line 19

I know that I am missing something basic on this, but not sure exactly how to get around it. When remove the --- out of the code, and then create a textbox and manually set the style, it works.. so I know that I am doing something wrong with the triggers... and I am sure it is something basic and 'newbie' ish...

any help would be appreciated.. :)

Here is the latest version

<Window.Resources>
    <Style x:Key="WMCTextBoxStyle"
       TargetType="TextBox">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBoxBase}">
                    <Border x:Name="border"
                           Background="{TemplateBinding Background}"
                             BorderBrush="{TemplateBinding BorderBrush}"
                             BorderThickness="{TemplateBinding BorderThickness}"
                             SnapsToDevicePixels="True">
                        <ScrollViewer x:Name="PART_ContentHost"
                                    Focusable="false"
                                    HorizontalScrollBarVisibility="Hidden"
                                    VerticalScrollBarVisibility="Hidden" />

                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled"
                                Value="false">
                            <Setter Property="Opacity"
                                   TargetName="border"
                                    Value="0.56" />
                        </Trigger>
                        <Trigger Property="IsMouseOver"
                                   Value="True">

                            <Setter TargetName="border">
                                <Setter.Value>
                                    <Border Name="OuterBorder"
                                CornerRadius="3"
                                Padding="2"
                                BorderThickness="1"
                                Height="Auto" 
                                Width="auto" 
                                VerticalAlignment="Center" 
                                HorizontalAlignment="Center">
                                        <Border.BorderBrush>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="#FFA4B3C5" Offset="0"/>
                                                <GradientStop Color="#FFA4B3C5" Offset="1"/>
                                            </LinearGradientBrush>
                                        </Border.BorderBrush>
                                        <Border Name="InnerBorder"
                                          CornerRadius="0"
                                            BorderThickness="1"
                                            VerticalAlignment="Center" 
                                             HorizontalAlignment="Center"
                                             BorderBrush="Black">
                                            <Border.Background>
                                                <RadialGradientBrush GradientOrigin="0.225,-0.616" RadiusY="0.863" RadiusX="0.757">
                                                    <GradientStop Color="#EEFFFFFF"/>
                                                    <GradientStop Color="#00FFFFFF" Offset="0.696"/>
                                                </RadialGradientBrush>
                                            </Border.Background>
                                        </Border>
                                    </Border>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</Window.Resources>

CodePudding user response:

To understand how styles work, I recommend the following read (better don't skip it): How to create a style for a control (WPF .NET) (and Styles and templates in WPF).

"Error XDG0062 '{DependencyProperty.UnsetValue}' is not a valid value for the 'System.Windows.Controls.Control.Template' property on a Setter." in Line:12"

You can't base a Style n itself (doesn't make sense either - I'm sure this also creates a designer error, showing squiggles to indicate the exact erroneous piece of code).

<!-- Illegal 'BasedOn' reference to itself as base style -->
<Style x:Key="WMCTextBoxStyle" 
       BasedOn="{StaticResource WMCTextBoxStyle}">

"Error XDG0062 Style object is not allowed to affect the Style property of the object to which it applies. in Line 19"

You can't set the Style property from inside a Style that is the current value of the Style property. Apart from that it does not make sense to set the Style prooperty to itself.

<!-- Illegal modification of the Style property. Aside from that
     'WMCTextBoxStyle' is already the Style, otherwise the triggers are not in effect -->
<Setter Property="Style" Value="{DynamicResource WMCTextBoxStyle}"/>

When you define an explicit Style (a named Style), you must assign it explictly:

<TextBox Style="{StaticResource WMCTextBoxStyle}" />

The simplest Style to change the BorderThickness, Background and BorderBrush on mouse over is:

<Window>
  <Window.Resources>
    <Style x:Key="WMCTextBoxStyle"
           TargetType="TextBox">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type TextBoxBase}">
            <Border x:Name="border"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    SnapsToDevicePixels="True">
              <ScrollViewer x:Name="PART_ContentHost"
                            Focusable="false"
                            HorizontalScrollBarVisibility="Hidden"
                            VerticalScrollBarVisibility="Hidden" />
            </Border>
            <ControlTemplate.Triggers>
              <Trigger Property="IsEnabled"
                       Value="false">
                <Setter Property="Opacity"
                        TargetName="border"
                        Value="0.56" />
              </Trigger>
              <Trigger Property="IsMouseOver"
                       Value="True">
                <Setter Property="BorderThickness"
                        Value="2" />
                <Setter Property="BorderBrush"
                        Value="OrangeRed" />
                <Setter Property="Background"
                        Value="PaleGreen" />
              </Trigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Window.Resources>

  <!-- Apply the Style -->
  <TextBox Style="{StaticResource WMCTextBoxStyle}" />
</Window>

If you are not interested in modifying the BorderBrush you can even skip the complete template and move the triggers to the Style.Triggers property.

CodePudding user response:

Here is the updated code:


<Window.Resources>
    <Style x:Key="WMCTextBoxStyle"
       TargetType="TextBox">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBoxBase}">
                    <Border x:Name="border"
                             Background="{TemplateBinding Background}"
                             BorderBrush="{TemplateBinding BorderBrush}"
                             BorderThickness="{TemplateBinding BorderThickness}"
                             SnapsToDevicePixels="True">
                        <ScrollViewer x:Name="PART_ContentHost"
                                    Focusable="false"
                                    HorizontalScrollBarVisibility="Hidden"
                                    VerticalScrollBarVisibility="Hidden" />

                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled"
                                Value="false">
                            <Setter Property="Opacity"
                                   TargetName="border"
                                    Value="0.56" />
                        </Trigger>
                        <Trigger Property="IsMouseOver"
                                   Value="True">

                            <Setter TargetName="border">
                                <Setter.Value>
                                    <Border Name="OuterBorder"
                                CornerRadius="3"
                                Padding="2"
                                BorderThickness="1"
                                Height="Auto" 
                                Width="auto" 
                                VerticalAlignment="Center" 
                                HorizontalAlignment="Center">
                                        <Border.BorderBrush>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="#FFA4B3C5" Offset="0"/>
                                                <GradientStop Color="#FFA4B3C5" Offset="1"/>
                                            </LinearGradientBrush>
                                        </Border.BorderBrush>
                                        <Border Name="InnerBorder"
                                          CornerRadius="0"
                                            BorderThickness="1"
                                            VerticalAlignment="Center" 
                                             HorizontalAlignment="Center"
                                             BorderBrush="Black">
                                            <Border.Background>
                                                <RadialGradientBrush GradientOrigin="0.225,-0.616" RadiusY="0.863" RadiusX="0.757">
                                                    <GradientStop Color="#EEFFFFFF"/>
                                                    <GradientStop Color="#00FFFFFF" Offset="0.696"/>
                                                </RadialGradientBrush>
                                            </Border.Background>
                                        </Border>
                                    </Border>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</Window.Resources>

When I actually use it as a style for the textbox control, that is when I get the error message. Here is an example of how I am using it in a textbox:

    <TextBox x:Name="inner" Text=" Return To Previous Folder" Grid.Row="2" Foreground="white" FontSize="35"  Style="{DynamicResource WMCTextBoxStyle}" Grid.ColumnSpan="3" Margin="190,10,50,174" />

If you want/need the full form code, I can post that as well.

  • Related