SkillAgentSearch skills...

Gu.Wpf.Adorners

No description available

Install / Use

/learn @GuOrg/Gu.Wpf.Adorners
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Gu.Wpf.Adorners

License NuGet Build Status Build status

A collection of adorners for wpf.

About

An Adorner is a custom FrameworkElement that is bound to a UIElement. Adorners are rendered in an AdornerLayer, which is a rendering surface that is always on top of the adorned element or a collection of adorned elements.

With Gu.Wpf.Adorners you can Overlay / Watermark multiple controls.

How to install

In a WPF application, install from NuGet.

```powershell
PM> install-package Gu.Wpf.Adorners
```

NuGet installs the dll, and adds it as a resource to your project.

Watermark

Basic Usage

Add the namespace to your control.

<UserControl ...
             xmlns:adorners="http://gu.se/Adorners">

TextBox

<TextBox adorners:Watermark.Text="Write something here" />

PasswordBox

<PasswordBox adorners:Watermark.Text="Write something here" />

ComboBox

<ComboBox adorners:Watermark.Text="Write something here">
    <ComboBoxItem>abc</ComboBoxItem>
    <ComboBoxItem>cde</ComboBoxItem>
    <ComboBoxItem>fgh</ComboBoxItem>
</ComboBox>

Advanced Usage

The below examples apply to TextBox, PasswordBox and ComboBox.

Binding

Instead of setting a static text as watermark, you can bind its value:

<!--Bind to the Text property of a different Element-->
<TextBox adorners:Watermark.Text="{Binding Text, ElementName=ElementNameHere}" />

<!--Bind to a property in your ViewModel/codebehind (make sure to set Datacontext)-->
<TextBox adorners:Watermark.Text="{Binding Path=SomeProperty}" />

<!--Bind to a static resource using the Gu.Wpf.Localization localization plugin-->
<TextBox adorners:Watermark.Text="{l:Static p:Resources.Label_Password}" />

For more info about the localization plugin, have a look at Gu.Wpf.Localization

Attached Properties

All properties are attached properties so you can do:

<StackPanel adorners:Watermark.Text="Write something here"
            adorners:Watermark.TextStyle="{StaticResource AdornerTextStyle}"
            adorners:Watermark.VisibleWhen="EmptyAndNotKeyboardFocused">
    <TextBox Text="{Binding SomeProp}"/>
    <TextBox Text="{Binding SomeOtherProp}" />
</StackPanel>

Inheriting Style

The Watermark inherits the following styles from the UIElement:

  • FontFamily
  • FontStyle
  • FontWeight
  • FontStretch
  • FontSize
  • Foreground
  • TextEffects

The below example will show a font 32 and bold watermark.

<TextBox adorners:Watermark.Text="Foo"
         FontSize="32"
         FontWeight="Bold"/>

Explicit Styling

Beside inheriting style, you can explicitly set it.

<UserControl.Resources>
    <Style x:Key="AdornerTextStyle" TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Green" />
        <Setter Property="Opacity" Value="1" />
    </Style>
</UserControl.Resources>
...
<Grid>
    <!--Style is set explicitly. The Watermark will render with a green Foreground.-->
    <TextBox adorners:Watermark.Text="Explicit style"
             adorners:Watermark.TextStyle="{StaticResource AdornerTextStyle}" />
</Grid>

By setting the adorners:Watermark to a ContentControl/Panel (Grid, GroupBox, StackPanel, etc.), all TextBox, PasswordBox and ComboBox children inherit the value.

<UserControl.Resources>
    <Style x:Key="AdornerTextStyle" TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Green" />
        <Setter Property="Opacity" Value="1" />
    </Style>
    <Style TargetType="{x:Type GroupBox}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="BorderThickness" Value="1" />
    </Style>
</UserControl.Resources>
...
<Grid>
    <!--By setting the Watermark.TextStyle on the ContentContol/Panel, all children inherit the TextStyle.-->
    <!--Same goes for Text and VisibleWhen (see below)-->
    <GroupBox adorners:Watermark.Text="Inherited style"
              adorners:Watermark.TextStyle="{StaticResource AdornerTextStyle}"
              Header="Inherited style">
        <StackPanel>
            <TextBox />
            <TextBox />
        </StackPanel>
    </GroupBox>

    <!--Both TextBox will render with the same Watermark Text: "Inherited text"-->
    <GroupBox adorners:Watermark.Text="Inherited text" Header="Inherited text">
        <StackPanel>
            <TextBox />
            <TextBox />
        </StackPanel>
    </GroupBox>

    <!--The top 3 elements inherit the same Watermark Text, the last one will use its own.-->
    <GroupBox adorners:Watermark.Text="Inherited text" Header="Inherited text">
        <StackPanel>
            <TextBox />
            <PasswordBox />
            <ComboBox />
            <TextBox adorners:Watermark.Text="This textbox does not inherit" />
        </StackPanel>
    </GroupBox>
</Grid>

TextStyle

TextStyle accepts a style for TextBlock the text is drawn where the textbox text is drawn so no margins needed.

<PasswordBox adorners:Watermark.Text="PASSWORD">
    <adorners:Watermark.TextStyle>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="Opacity" Value="0.5" />
            <Setter Property="FontStyle" Value="Oblique" />
            <Setter Property="VerticalAlignment" Value="Center" />
        </Style>
    </adorners:Watermark.TextStyle>
</PasswordBox>

Visibility

The behaviour of the watermark can be set with the VisibleWhen property.

<!--The watermark shows as long as the control has no value.-->
<TextBox adorners:Watermark.Text="visible when empty"
         adorners:Watermark.VisibleWhen="Empty" />

<!--The watermark shows as long as the control has no value and is not focused.-->
<TextBox adorners:Watermark.Text="visible when not keyboard focused (default)"
         adorners:Watermark.VisibleWhen="EmptyAndNotKeyboardFocused" />

Rendered Example

The above examples render to the following visualisation:

watermarked

Watermark Properties

Watermark.Text

The text displayed as watermark in the UIElement.

Watermark.VisibleWhen

  • Empty
  • EmptyAndNotKeyboardFocused (Default)

Watermark.TextStyle

TextStyle accepts a style for TextBlock the text is drawn where the textbox text is drawn so no margins needed.

Default Watermark Style

<Style TargetType="{x:Type local:WatermarkAdorner}">
    <Setter Property="IsHitTestVisible" Value="False" />
    <Setter Property="Focusable" Value="False" />
    <Setter Property="TextElement.FontFamily" Value="{Binding AdornedTextBox.FontFamily, RelativeSource={RelativeSource Self}}" />
    <Setter Property="TextElement.FontStyle" Value="{Binding AdornedTextBox.FontStyle, RelativeSource={RelativeSource Self}}" />
    <Setter Property="TextElement.FontWeight" Value="{Binding AdornedTextBox.FontWeight, RelativeSource={RelativeSource Self}}" />
    <Setter Property="TextElement.FontStretch" Value="{Binding AdornedTextBox.FontStretch, RelativeSource={RelativeSource Self}}" />
    <Setter Property="TextElement.FontSize" Value="{Binding AdornedTextBox.FontSize, RelativeSource={RelativeSource Self}}" />
    <Setter Property="TextElement.Foreground" Value="{Binding AdornedTextBox.Foreground, RelativeSource={RelativeSource Self}}" />
    <Setter Property="TextElement.TextEffects" Value="{Binding Path=(TextElement.TextEffects), RelativeSource ={RelativeSource Self}}" />

    <Setter Property="TextStyle">
        <Setter.Value>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="Opacity" Value="0.5" />
                <Setter Property="FontStyle" Value="Oblique" />
            </Style>
        </Setter.Value>
    </Setter>
</Style>

Overlay

For adding an overlay to an element. The overlay visibility is controlled with adorners:Overlay.Visibility.

Sample:

<Button adorners:Overlay.Visibility="{Binding IsChecked,
                                              ElementName=IsVisibleButton,
                                              Converter={StaticResource BooleanToVisibilityConverter}}">
    <adorners:Overlay.Content>
        <Border BorderBrush="HotPink"
                BorderThickness="2" />
    </adorners:Overlay.Content>
</Button>

Renders: overlay

Attached properties

All properties are attached properties so you can do: Note that this sample makes little sense overspecifying, providing it to give copy-paste friendly xaml.

<StackPanel adorners:O
View on GitHub
GitHub Stars93
CategoryDevelopment
Updated4mo ago
Forks11

Languages

C#

Security Score

87/100

Audited on Dec 3, 2025

No findings