https://github.com/guorg/gu.wpf.adorners
https://github.com/guorg/gu.wpf.adorners
Last synced: about 1 year ago
JSON representation
- Host: GitHub
- URL: https://github.com/guorg/gu.wpf.adorners
- Owner: GuOrg
- License: mit
- Created: 2016-02-04T15:45:53.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2023-12-25T13:09:28.000Z (over 2 years ago)
- Last Synced: 2025-04-06T19:12:24.560Z (about 1 year ago)
- Language: C#
- Size: 910 KB
- Stars: 90
- Watchers: 5
- Forks: 12
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Gu.Wpf.Adorners
[](LICENSE) [](https://www.nuget.org/packages/Gu.Wpf.Adorners/)
[](https://dev.azure.com/guorg/Gu.Wpf.Adorners/_build/latest?definitionId=5&branchName=master)
[](https://ci.appveyor.com/project/JohanLarsson/gu-wpf-adorners)
## A collection of adorners for wpf.
- [About](#about)
- [How to install](#How-to-install)
- [Watermark](#watermark)
- [Basic Usage](#basic-usage)
- [TextBox](#textbox)
- [PasswordBox](#passwordbox)
- [ComboBox](#combobox)
- [Advanced Usage](#advanced-usage)
- [Binding](#binding)
- [Attached Properties](#attached-properties)
- [Inheriting Style](#inheriting-style)
- [Explicit Styling](#explicit-styling)
- [TextStyle](#textstyle)
- [Visibility](#visibility)
- [Rendered Example](#rendered-example)
- [Watermark Properties](#watermark-properties)
- [Watermark.Text](#watermarktext)
- [Watermark.VisibleWhen](#watermarkvisiblewhen)
- [Watermark.TextStyle](#watermarktextstyle)
- [Default Watermark Style](#default-watermark-style)
- [Overlay](#overlay)
- [Attached properties](#attached-properties)
- [Info](#info)
- [DragAdorner](#dragadorner)
# 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.
```xaml
```
### TextBox
```xaml
```
### PasswordBox
```xaml
```
### ComboBox
```xaml
abc
cde
fgh
```
## 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:
```xaml
```
*For more info about the localization plugin, have a look at [Gu.Wpf.Localization](https://github.com/GuOrg/Gu.Localization)*
### Attached Properties
All properties are attached properties so you can do:
```xaml
```
### 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.
```xaml
```
### Explicit Styling
Beside inheriting style, you can explicitly set it.
```xaml
<Setter Property="Foreground" Value="Green" />
<Setter Property="Opacity" Value="1" />
...
```
By setting the `adorners:Watermark` to a ContentControl/Panel (Grid, GroupBox, StackPanel, etc.), all TextBox, PasswordBox and ComboBox children inherit the value.
```xaml
<Setter Property="Foreground" Value="Green" />
<Setter Property="Opacity" Value="1" />
<Setter Property="BorderBrush" Value="Blue" />
<Setter Property="BorderThickness" Value="1" />
...
```
### TextStyle
TextStyle accepts a style for `TextBlock` the text is drawn where the textbox text is drawn so no margins needed.
```xaml
<Setter Property="Opacity" Value="0.5" />
<Setter Property="FontStyle" Value="Oblique" />
<Setter Property="VerticalAlignment" Value="Center" />
```
### Visibility
The behaviour of the watermark can be set with the `VisibleWhen` property.
```xaml
```
### Rendered Example
The above examples render to the following visualisation:

## 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
```xaml
<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" />
```
# Overlay
For adding an overlay to an element.
The overlay visibility is controlled with `adorners:Overlay.Visibility`.
Sample:
```xaml
```
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.
```xaml
```
# Info
This is very similar to the adorner used for validation in WPF.
Sample:
```xaml
```
Renders: 
The DataContext of the adorner is bound to DataContext of AdornedElement.
# DragAdorner
Shows an adorner that follows the mouse while draging in a drag & drop operation.

Sample:
```cs
private static bool TryGetDropTarget(object sender, out ContentPresenter target)
{
target = null;
if (sender is ContentPresenter cp &&
cp.Content == null)
{
target = cp;
}
return target != null;
}
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.Source is ContentPresenter contentPresenter &&
contentPresenter.Content != null)
{
var data = new DataObject(typeof(DragItem), contentPresenter.Content);
using (var adorner = DragAdorner.Create(contentPresenter))
{
data.SetData(typeof(Adorner), adorner);
contentPresenter.SetCurrentValue(ContentPresenter.ContentProperty, null);
DragDrop.DoDragDrop(contentPresenter, data, DragDropEffects.Move);
var target = data.GetData(typeof(UIElement));
if (target == null)
{
contentPresenter.SetCurrentValue(ContentPresenter.ContentProperty, data.GetData(typeof(DragItem)));
}
}
}
}
private void OnDrop(object sender, DragEventArgs e)
{
if (TryGetDropTarget(e.Source, out var contentPresenter))
{
contentPresenter.SetCurrentValue(ContentPresenter.ContentProperty, e.Data.GetData(typeof(DragItem)));
e.Effects = DragDropEffects.Move;
e.Data.SetData(typeof(UIElement), contentPresenter);
e.Handled = true;
}
}
private void OnDragLeave(object sender, DragEventArgs e)
{
if (TryGetDropTarget(e.Source, out var contentPresenter) &&
e.Data.GetData(typeof(Adorner)) is ContentDragAdorner adorner)
{
adorner.RemoveSnap(contentPresenter);
e.Effects = DragDropEffects.None;
e.Handled = true;
}
}
private void OnDragEnter(object sender, DragEventArgs e)
{
if (TryGetDropTarget(e.Source, out var contentPresenter) &&
e.Data.GetData(typeof(Adorner)) is ContentDragAdorner adorner)
{
adorner.SnapTo(contentPresenter);
e.Effects = DragDropEffects.Move;
e.Handled = true;
}
}
```