Question

I've got the below style for TextBoxes in my WPF app:

<!-- http://www.thexamlproject.com/ -->
<Style x:Key="LockIcon" TargetType="Path">
    <Setter Property="Height" Value="16" />
    <Setter Property="Width" Value="16" />
    <Setter Property="Stretch" Value="Uniform" />
    <Setter Property="Data" 
            Value="F1 M 80.6667,55.1172L 80.6667,35.3333C 80.6667,15.851 64.815,3.05176e-005 45.3333,3.05176e-005C 25.8509,3.05176e-005 9.99998,15.851 9.99998,35.3333L 9.99998,55.1172L 0,56L 0,129.333L 45.3333,133.333L 90.6667,129.333L 90.6667,56L 80.6667,55.1172 Z M 20.6667,54.1771L 20.6667,35.3333C 20.6667,21.7318 31.7317,10.6667 45.3333,10.6667C 58.9349,10.6667 70,21.7318 70,35.3333L 70,54.1771L 45.3333,52L 20.6667,54.1771 Z " />
</Style>

<VisualBrush x:Key="LockBrush" Stretch="None" AlignmentX="Left">
    <VisualBrush.Visual>
        <Border BorderThickness="4" BorderBrush="Transparent">
            <Path Style="{StaticResource LockIcon}" Fill="Red" />
        </Border>
    </VisualBrush.Visual>
</VisualBrush>

<Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}">
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Background" Value="{StaticResource LockBrush}"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="Padding" Value="22,4"/>
        </Trigger>
    </Style.Triggers>
</Style>

I can't seem to find a good way to apply this VisualBrush image AND a background color to the entire TextBox. I either get strange stretching issues or simply cannot fill the whole TextBox (controls stretch and are different widths depending on the rendering view).

Ideas?

Was it helpful?

Solution

Instead of a VisualBrush use a Control Template.

XAML

<Style x:Key="LockIcon"
           TargetType="Path">
      <Setter Property="Height"
              Value="16" />
      <Setter Property="Width"
              Value="16" />
      <Setter Property="Stretch"
              Value="Uniform" />
      <Setter Property="Data"
              Value="F1 M 80.6667,55.1172L 80.6667,35.3333C 80.6667,15.851 64.815,3.05176e-005 45.3333,3.05176e-005C 25.8509,3.05176e-005 9.99998,15.851 9.99998,35.3333L 9.99998,55.1172L 0,56L 0,129.333L 45.3333,133.333L 90.6667,129.333L 90.6667,56L 80.6667,55.1172 Z M 20.6667,54.1771L 20.6667,35.3333C 20.6667,21.7318 31.7317,10.6667 45.3333,10.6667C 58.9349,10.6667 70,21.7318 70,35.3333L 70,54.1771L 45.3333,52L 20.6667,54.1771 Z " />
    </Style>

    <Style TargetType='TextBox'
           x:Key='WithLockIcon'>
      <Setter Property='MinHeight'
              Value='26' />
      <Setter Property="Padding"
              Value="22,4" />
      <Style.Triggers>
        <Trigger Property="IsEnabled"
                 Value="false">
          <!-- Use a control template instead of 
               Background property -->
          <!--<Setter Property="Background"
                  Value="{StaticResource LockBrush}" />-->
          <!--<Setter Property="Padding"
                  Value="22,4" />-->

          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type TextBoxBase}">
                <!-- Set background here!-->
                <Border BorderThickness="4"
                        BorderBrush="Transparent"
                        HorizontalAlignment='Stretch'>
                  <StackPanel Background='#dddddd'
                              Orientation='Horizontal'>
                    <Path Style="{StaticResource LockIcon}"
                          Fill="Red" />
                    <ScrollViewer Margin="0"
                                  x:Name="PART_ContentHost">

                    </ScrollViewer>

                  </StackPanel>
                </Border>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Trigger>

      </Style.Triggers>
    </Style>
  </Window.Resources>
  <StackPanel>
    <TextBox x:Name='textbox1'
             Text='Example Text'
             IsEnabled='False'
             Style='{StaticResource WithLockIcon}' />
    <ToggleButton Checked='ToggleButton_Checked'
                  Unchecked='ToggleButton_Unchecked'
                  Content='Change State' />
  </StackPanel>

OTHER TIPS

I've achieved a reasonably close simulation in a similar situation.

<Window x:Class="VisualBrushMargins.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        Background="{DynamicResource WindowBackground}">
    <Window.Resources>
        <VisualBrush x:Key="WindowBackground" Stretch="UniformToFill">
            <VisualBrush.Visual>
                <Grid>
                    <Border Background="DarkGreen" Width="250" Height="150" />
                    <Canvas Height="130" Width="180" Background="DarkBlue">
                        <Path>
                            <!-- path goes here -->
                        </Path>
                        <Ellipse Width="100" Height="100" Stroke="Red" />
                    </Canvas>
                </Grid>
            </VisualBrush.Visual>
        </VisualBrush>
    </Window.Resources>
    <Grid/>
</Window>

what it looks like

The path fits the canvas. Sizing the canvas and the border differently allows to add a "margin" to the brush -- note how it behaves on window resize. (Canvas is colored blue for illustrational purpose -- actually it's supposed to be transparent)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top