NANDAKUMAR THANGAVELU
NANDAKUMAR THANGAVELU

Reputation: 661

Water Mark Text Box

<Style TargetType="TextBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Grid>
                    <Border BorderBrush="Red" CornerRadius="2" />
                    <ScrollViewer x:Name="PART_ContentHost"  VerticalAlignment="Center"         HorizontalAlignment="Center"/>
                    <Label x:Name="watermarklabel" Height="40" Content="{TemplateBinding Tag}" Foreground="Gray"/>
                </Grid>

                <ControlTemplate.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Value="True">
                                <Condition.Binding>
                                    <MultiBinding Converter="{StaticResource Multi}">
                                        <!--<Binding Path="Text" ElementName="txt1"/>-->
                                        <Binding RelativeSource="{RelativeSource Mode=TemplatedParent}"  Path="Text"/>
                                    </MultiBinding>
                                </Condition.Binding>
                            </Condition>
                        </MultiDataTrigger.Conditions>

                        <Setter Property="Visibility" TargetName="watermarklabel" Value="Collapsed"/>
                    </MultiDataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Here i want to enable/disable the label (which is water mark) upon the condition when the textbox text is empty and not empty. In the multi binding i am trying to access the text property using the TemplatedParent. But it is not hitting convertor when text changed.

When i use the element name to access it everything is fine.

But i want to make generic this one..

How to make this to work?

Thanks in advance..

Upvotes: 2

Views: 569

Answers (1)

Greg D
Greg D

Reputation: 44076

This is actually surprisingly tricky to get right. There are a dozen different almost-right answers on the internet, but few or no completely correct ones.

The closest I've ever come to getting this to work correctly is to dynamically inject a textblock into the standard textbox's ControlTemplate at runtime based on the conditions that you're evaluating.

  1. Dynamic injection avoids having to re-implement the entire controltemplate and, assuming the control template doesn't transform too much between versions, also avoids the maintenance point of having to create new ControlTemplates every time built-in theming changes.

  2. Injecting an element instead of modifying the existing text element avoids all kinds of problems where users can select/manipulate the watermark text in undesirable ways.

  3. Avoid an overlaying solution: the z-order and clipping issues aren't worth the effort (I once tried to do this with a decorator, not the right call)

  4. Don't forget to verify that Drag/Drop and Copy/Paste operations on the text box work as expected with the watermark.

  5. IIRC, I did it with an attached property so that a watermark didn't require a new control. Rather, it searched the visual tree for the first viable watermark target it could find and applied the watermark there. This let it work in a combobox as well, e.g., without add'l work.

Upvotes: 1

Related Questions