[3] WPF practical tutorial support watermark with a clear function of the input box

1 Introduction:

WPF practical tutorial [2] (In this part based on an article Click here to jump Solutions) to create presentations.

This chapter has cleared a custom function input box, take you into the content WPF custom control development, focusing on presentation creation methods, some of which relate to the theoretical knowledge will be briefly mentioned, the focus will not explain, will follow in the Advanced articles explain in.

Finally, engineering renderings:

2. clean-up project related content

Before making your presentation, content within the first project to clean up, as shown below

4 MainWindow.xaml in the line, line 9-12 deleted, the deleted below

The MicroUI.Wpf.Toolkit project CustomControl.cs deleted

The Themes \ Generic.xaml file in the first 5-17 rows deleted

MicroUI.Wpf.Toolkit project content after clean-up is as follows:

Well, this next cleanup is very clean, you can rebuild the solution and run to see if this time there is no solution to the problem:

I have no problem, the following can be demonstrated.

3. Custom Control Project

3.1 New Custom Controls

Right-click MicroUI.Wpf.Toolkit project, select "Add" \ "New Item"

According to the order of the arrow to select "WPF" \ "Custom Controls (WPF)", the name for the ClearTextBox.cs, then click on the "Add" button in order.

At this point, the project increased the ClearTextBox.cs and Generic.xaml added to its default style:

 

In order to facilitate management control, I'll put the contents of each of the controls are placed in their own folder, so ClearTextBox then create a new folder:

ClearTextBox.cs then drag the folder to the new ClearTextBox:

Then, create a resource file in the folder ClearTextBox file:

Resource file named Themes.xaml

After you add the following:

The ClearTextBox \ Themes.xaml content amended as follows:


<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MicroUI.Wpf.Toolkit">

    <Style TargetType="{x:Type local:ClearTextBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ClearTextBox}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</Style>
    
</ResourceDictionary>

The Themes \ Generic.xaml code is modified as follows:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MicroUI.Wpf.Toolkit">


    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/MicroUI.Wpf.Toolkit;component/ClearTextBox/Themes.xaml" />

    </ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

Then modify MicroUI.Wpf.Samples project MainWindow.xaml reads as follows:


<Window x:Class="MicroUI.Wpf.Samples.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:microui="clr-namespace:MicroUI.Wpf.Toolkit;assembly=MicroUI.Wpf.Toolkit"
        Title="MainWindow" Height="350" Width="525">

    <Grid>
        <microui:ClearTextBox Width="100" Height="30" 
                          VerticalAlignment="Center"
                          HorizontalAlignment="Center" />
    </Grid>

</Window>

run:

Nothing. Let's start modifying the control.

3.2 modify custom control

The ClearTextBox inherited Control into TextBox, as shown below:

Then modify ClearTextBox \ Themes.xaml reads as follows:


<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MicroUI.Wpf.Toolkit">

    <Style TargetType="{x:Type local:ClearTextBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ClearTextBox}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <!--文本内容区域-->
                            <ScrollViewer x:Name="PART_ContentHost"/>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</Style>
    
</ResourceDictionary>

We can see that in fact only added the following:

Then modify MainWindow.xaml reads as follows:

Since ClearTextBox inherited TextBox, so you can set the Text property, run:

We can see the effect of running. Note my words in ClearBox \ Themes.xaml of Canada:

This sentence seems very simple, in fact, one of the PART _ *** name, a lot of information, but I'm here in passing, namely:

ScrollViewer's "PART_ContentHost" name, WPF is built a special name, in this control, it indicates that the ScrollViewer is used to load text content of the TextBox. PART_ContentHost the name can only be used ScrollViewer or Adorner, Decorator control.

Next, we want to add a Clear button:

3.3 Add clear button

Re modify ClearBox \ Themes.xaml document reads as follows:

And then build the solution, re-run:

We can see've got a button. Style is quite ugly, first regardless of style, functional say.

Button to add 3.4 to clearance

I can see the clear button to assign a name PART_ClearButtonHost in ClearBox \ Themes.xaml in

Then I'll change it again ClearTextBox.cs, modified as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MicroUI.Wpf.Toolkit
{

    [TemplatePart(Name = "PART_ClearButtonHost", Type = typeof(ButtonBase))]
    public class ClearTextBox : TextBox
    {
        private ButtonBase clearButtonHost;
        static ClearTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ClearTextBox), new FrameworkPropertyMetadata(typeof(ClearTextBox)));
        }

        #region  继承事件
        //模板化控件在加载ControlTemplate后会调用OnApplyTemplate
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (clearButtonHost != null)
            {
                clearButtonHost.Click -= HandleClearButtonClick;
            }
            clearButtonHost = GetTemplateChild("PART_ClearButtonHost") as ButtonBase;
            if (clearButtonHost != null)
            {
                clearButtonHost.Click += HandleClearButtonClick;
            }

        }

        #endregion

        #region 方法
        //清除事件
        private void HandleClearButtonClick(object sender, RoutedEventArgs e)
        {
            Reset();
        }

        public void Reset()
        {
            Text = String.Empty;

        }
        #endregion

    }

}

Note: Do not try to call GetTemplateChild in Loaded event, because Loaded before OnApplyTemplate call and Loaded more likely to be triggered multiple times. Since Template may be loaded multiple times, or can not get TemplatePart correct, so before using TemplatePart should first determine whether it is empty; if you want to subscribe to an event, you should cancel your subscription.

GetTemplateChild complete the following steps:

  • Unsubscribe TemplatePart event

  • The TemplatePart stored in a private field

  • Subscribe TemplatePart event

More detailed significance of TemplatePart temporarily not explain, will be used first, then go to get to the bottom significance.

Rebuild Solution, run the program:

You can see, it has been running.

To finish up here yet, we hope that if there is data to show the clear button, no data is hidden clear button, then we will achieve this demand.

3.5 is determined whether or not the data is empty

Next, we again modify ClearTextBox.cs, to increase its IsHasText of a property.

Then reload OnTextChanged () event,

At this time, a complete code is as follows:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MicroUI.Wpf.Toolkit
{

    [TemplatePart(Name = "PART_ClearButtonHost", Type = typeof(ButtonBase))]
    public class ClearTextBox : TextBox
    {
        private ButtonBase clearButtonHost;
        static ClearTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ClearTextBox), new FrameworkPropertyMetadata(typeof(ClearTextBox)));
        }

        #region 输入框内是否有数据
        [Browsable(false)]
        public bool IsHasText
        {
            get { return (bool)GetValue(IsHasTextProperty); }
            private set { SetValue(IsHasTextPropertyKey, value); }
        }
        private static readonly DependencyPropertyKey IsHasTextPropertyKey =
            DependencyProperty.RegisterReadOnly(
                "IsHasText",
                typeof(Boolean),
                typeof(ClearTextBox),
                new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));
        public static readonly DependencyProperty IsHasTextProperty =
            IsHasTextPropertyKey.DependencyProperty;


        #endregion

        #region  继承事件
        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            base.OnTextChanged(e);
            IsHasText = !String.IsNullOrEmpty(Text);
        }

        //模板化控件在加载ControlTemplate后会调用OnApplyTemplate
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (clearButtonHost != null)
            {
                clearButtonHost.Click -= HandleClearButtonClick;
            }
            clearButtonHost = GetTemplateChild("PART_ClearButtonHost") as ButtonBase;
            if (clearButtonHost != null)
            {
                clearButtonHost.Click += HandleClearButtonClick;
            }

        }

        #endregion

        #region 方法
        //清除事件
        private void HandleClearButtonClick(object sender, RoutedEventArgs e)
        {
            Reset();
        }

        public void Reset()
        {
            Text = String.Empty;

        }
        #endregion

    }

}

Then we want to show the clear button to complete or not according to IsHasText property, using the style of the trigger. Modify ClearTextBox \ Themes.xaml reads as follows:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MicroUI.Wpf.Toolkit">

    <Style TargetType="{x:Type local:ClearTextBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ClearTextBox}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            
                            <!--文本内容区域-->
                            <ScrollViewer x:Name="PART_ContentHost" Grid.Column="1" VerticalAlignment="Center"/>
                            <!--清除按钮-->
                            <Button x:Name="PART_ClearButtonHost" Grid.Column="2" 
                                    Padding="2,0" IsHitTestVisible="False" Visibility="Collapsed"
                                    Content="x"                                     
                                    />
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="UIElement.IsEnabled" Value="True"/>
                                <Condition Property="IsHasText" Value="True"/>
                            </MultiTrigger.Conditions>
                            <MultiTrigger.Setters>
                                <Setter TargetName="PART_ClearButtonHost" Property="IsHitTestVisible" Value="True"/>
                                <Setter TargetName="PART_ClearButtonHost" Property="Visibility" Value="Visible"/>
                            </MultiTrigger.Setters>
                        </MultiTrigger>
                        
                    </ControlTemplate.Triggers>

                    
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</Style>
    
</ResourceDictionary>

You can see that I first set PART_ClearButtonHost initial state are not visible:

Then add the template to trigger more than one condition:

Trigger conditions: control enabled and IsHastText to True, clear display and clickable buttons.

Then we re-build the solution, run:

The basic cleanup has been completed, but the style of it, a little bit ugly, then we beautify Clear style button.

3.6 Use iconfont landscaping button style

This section relates to the article [ WPF practical tutorial 1 - Use Iconfont icon font ] , is recommended to go look at this content .

Download the project file, extract the iconfont.ttf to Res directory

MicroUI.Wpf.Toolkit new project Fonts directory, as follows:

The iconfont.ttf into the Fonts directory:

New Style MicroUI.Wpf.Toolkit project directory, as follows:

New resource dictionary In Style directory, the file name MicroIcon.xaml:

Modify MicroIcon.xaml reads as follows:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Style x:Key="MicroBtnIcon" TargetType="{x:Type Button}">
        <Setter Property="FontFamily" Value="/MicroUI.Wpf.Toolkit;component/Fonts/#iconfont"></Setter>
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="Margin" Value="3" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border BorderBrush="{TemplateBinding Control.BorderBrush}" BorderThickness="0">
                        <ContentPresenter Content="{TemplateBinding ContentControl.Content}" 
                                          HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter Property="Opacity" Value="0.8" />
                        </Trigger>
                        <Trigger Property="IsPressed" Value="true">
                            <Setter Property="Opacity" Value="0.7" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>

            </Setter.Value>
        </Setter>
</Style>
    <Style x:Key="MicroBtnIcon_Close" TargetType="{x:Type Button}" BasedOn="{StaticResource MicroBtnIcon}" >
        <Setter Property="Content" Value="&#xe677;" />
</Style>

</ResourceDictionary>

Then add the following three sentences in ClearTextBox \ Themes.xaml in:

At the same time modify the Clear button as follows:

Rebuild Solution, run again:

At this point you can see the style has been pretty good.

3.7 Add a watermark

Next, I prepared plus a watermark. Edit ClearTextBox.cs, in which add the following words:

#region 水印
[Category("Extend Properties")]
public String WaterMark
{
  get { return (String)GetValue(WaterMarkProperty); }
   set { SetValue(WaterMarkProperty, value); }
}

public static readonly DependencyProperty WaterMarkProperty =
  DependencyProperty.Register("WaterMark", typeof(String), typeof(ClearTextBox), new PropertyMetadata(String.Empty));
#endregion

Add the following words in ClearTextBox \ Themes.xaml in:


 <!--水印区域-->
 <Label x:Name="watermark" Grid.Column="1"
    Content="{TemplateBinding WaterMark}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    IsHitTestVisible="False"
    Foreground="#CCCCCC"
    Margin="{TemplateBinding Padding}"
    Visibility="Collapsed"  />

And add the following words:

<MultiTrigger>
  <MultiTrigger.Conditions>
    <Condition Property="UIElement.IsEnabled" Value="True"/>
    <Condition Property="UIElement.IsFocused" Value="False"/>
    <Condition Property="TextBox.Text" Value=""/>
  </MultiTrigger.Conditions>
  <MultiTrigger.Setters>
    <Setter TargetName="watermark" Property="Visibility" Value="Visible"/>
  </MultiTrigger.Setters>
</MultiTrigger>

MainWindow.xaml MicroUI.Wpf.Samples modify the contents of the project are as follows:

<Window x:Class="MicroUI.Wpf.Samples.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:microui="clr-namespace:MicroUI.Wpf.Toolkit;assembly=MicroUI.Wpf.Toolkit"
        Title="MainWindow" Height="350" Width="525">

    <Grid>
        <StackPanel Orientation="Vertical" VerticalAlignment="Center">
            <microui:ClearTextBox Width="200" Height="30" 
                          VerticalAlignment="Center"
                          HorizontalAlignment="Center"
                          BorderBrush="#dddddd"
                          BorderThickness="1"
                          WaterMark="这里是水印"
                          Text="公众号:BigBearIT"/>
            <TextBox Text="这里是普通的TextBox" 
                     HorizontalAlignment="Center" 
                     VerticalContentAlignment="Center"
                     Width="200" Height="30" Margin="0,10" />
        </StackPanel>
    </Grid>
</Window>

Rebuild Solution, run the program:

Section 3.8

Benpian support by creating a watermarked input box clearance, to demonstrate the process to create a custom control, it is recommended that you first look at their own dependency properties, TemplatePart, I will be the right time to follow highlight some of these.

/////////////////////////////////////////////////////////////////////////////////////////

** original article, reproduced, please attach the declaration part

** Source: https://blog.csdn.net/mybelief321

** Author: Nine Zero Zhuang

/////////////////////////////////////////////////////////////////////////////////////////

Published 143 original articles · won praise 161 · Views 1.21 million +

Guess you like

Origin blog.csdn.net/mybelief321/article/details/102741177