Gu.Wpf.Adorners
No description available
Install / Use
/learn @GuOrg/Gu.Wpf.AdornersREADME
Gu.Wpf.Adorners
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:
FontFamilyFontStyleFontWeightFontStretchFontSizeForegroundTextEffects
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:

Watermark Properties
Watermark.Text
The text displayed as watermark in the UIElement.
Watermark.VisibleWhen
EmptyEmptyAndNotKeyboardFocused(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: 
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
