For an Placeholder/Watermark in an TextBox I use this Style get that to work:
<Style x:Key="placeHolder" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid Margin="15 0 15 0">
<TextBox Text="{Binding Path=Text,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
x:Name="textSource" TextWrapping="Wrap"
BorderBrush="Red" AcceptsReturn="True"
BorderThickness="0"
Background="Transparent"
Panel.ZIndex="2" />
<TextBox Text="{TemplateBinding Tag}" TextWrapping="Wrap" Background="{TemplateBinding Background}" Panel.ZIndex="1">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Foreground" Value="Transparent"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Text, Source={x:Reference textSource}}" Value="" />
<Condition Binding="{Binding printcontrol}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="LightGray"/>
<Setter Property="Visibility" Value="Hidden"/>
</MultiDataTrigger>
<DataTrigger Binding="{Binding Path=Text, Source={x:Reference textSource}}" Value="">
<Setter Property="Foreground" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But now I need to use an RichTextBox and now that doesn't work for that so what Ive tried is something like that:
<RichTextBox x:Name="Placeholder" Height="20" IsHitTestVisible="True" VerticalAlignment="Top" Margin="0,20,298.8,0" Foreground="DarkGray" HorizontalAlignment="Right" Width="214">
<FlowDocument>
<Paragraph>
<Run Foreground="Black">
<Run.Style>
<Style TargetType="{x:Type Run}">
<Setter Property="Foreground" Value="Transparent"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Text, Source={x:Reference textSource}}" Value="" />
<Condition Binding="{Binding printcontrol}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="LightGray"/>
<Setter Property="FontSize" Value="0.004"/>
</MultiDataTrigger>
<DataTrigger Binding="{Binding Path=Text, Source={x:Reference textSource}}" Value="">
<Setter Property="Foreground" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Run.Style>
</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
But that didn't work. Has someone an Idea how to get Placeholder RichTextBox
?
End Result should be something like that:
CodePudding user response:
Define a dependency property (boolean type) that will determine when show or hide a placeholder. The only problem here is how to determine the FlowDocument
is empty or not? Because of the RichTextBox
doesn’t have a method that return state of the document.
I think one of a good solution (regarding performance) described in the following post: Detect if a RichTextBox is empty.
The code below contains the OnDocumentChanged()
method that uses solution from the mentioned post:
public partial class MainWindow : Window
{
public bool IsDocumentEmpty
{
get { return (bool)GetValue(IsDocumentEmptyProperty); }
set { SetValue(IsDocumentEmptyProperty, value); }
}
public static readonly DependencyProperty IsDocumentEmptyProperty =
DependencyProperty.Register("IsDocumentEmpty", typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
public MainWindow()
{
InitializeComponent();
}
private void OnDocumentChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
if (sender is RichTextBox rtb)
{
int size = rtb.Document.ContentStart.GetOffsetToPosition(rtb.Document.ContentEnd);
IsDocumentEmpty = (size == 0 // The document has not blocks. Example, after Ctrl A & Delete.
|| size == 2 // The document has 1 block without inlines. For example, 1 paragraph without inline(s).
|| size == 4); // The document has 1 block and 1 paragraph with empty inline.
}
}
}
The XAML
:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
...
Height="350" Width="400">
<Window.Resources>
<ResourceDictionary>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=IsDocumentEmpty}"
Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid>
<RichTextBox x:Name="rtb" IsHitTestVisible="True" HorizontalAlignment="Right"
TextChanged="OnDocumentChanged"
Background="Transparent" Panel.ZIndex="2">
<FlowDocument x:Name="fdoc"/>
</RichTextBox>
<TextBox Text=" Enter text..." TextWrapping="Wrap" Panel.ZIndex="1" Foreground="DarkGray" />
</Grid>
</Grid>
</Window>