programing

텍스트 상자에 자리 표시자 텍스트 추가

megabox 2023. 5. 9. 22:12
반응형

텍스트 상자에 자리 표시자 텍스트 추가

저는 html5의 텍스트 상자에서 당신처럼 텍스트 상자에 자리 표시자 텍스트를 추가할 수 있는 방법을 찾고 있습니다.

즉, 텍스트 상자에 텍스트가 없는 경우 텍스트를 추가합니다.Enter some text here사용자가 플레이스홀더 텍스트를 누르면 플레이스홀더 텍스트가 사라지고 사용자가 자신의 텍스트를 입력할 수 있으며, 텍스트 상자에 포커스가 손실되고 텍스트가 없으면 플레이스홀더가 텍스트 상자에 다시 추가됩니다.

이와 같은 것이 아닐까요?

Textbox myTxtbx = new Textbox();
myTxtbx.Text = "Enter text here...";

myTxtbx.GotFocus += GotFocus.EventHandle(RemoveText);
myTxtbx.LostFocus += LostFocus.EventHandle(AddText);

public void RemoveText(object sender, EventArgs e)
{
    if (myTxtbx.Text == "Enter text here...") 
    {
     myTxtbx.Text = "";
    }
}

public void AddText(object sender, EventArgs e)
{
    if (string.IsNullOrWhiteSpace(myTxtbx.Text))
        myTxtbx.Text = "Enter text here...";
}

그것은 단지 의사 코드이지만 개념은 거기에 있습니다.

이것을 사용할 수 있습니다. 이것은 저에게 효과적이고 매우 간단한 해결책입니다.

    <Style x:Key="placeHolder" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Grid>
                        <TextBox Text="{Binding Path=Text,
                                                RelativeSource={RelativeSource TemplatedParent}, 
                                                Mode=TwoWay,
                                                UpdateSourceTrigger=PropertyChanged}"
                                 x:Name="textSource" 
                                 Background="Transparent" 
                                 Panel.ZIndex="2" />
                        <TextBox Text="{TemplateBinding Tag}" Background="{TemplateBinding Background}" Panel.ZIndex="1">
                            <TextBox.Style>
                                <Style TargetType="{x:Type TextBox}">
                                    <Setter Property="Foreground" Value="Transparent"/>
                                    <Style.Triggers>
                                        <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>

용도:

<TextBox Style="{StaticResource placeHolder}" Tag="Name of customer" Width="150" Height="24"/>

‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎

텍스트를 Windows 하여 포커를는처고제설텍위를하정거해스이기하트입벤및트표시력포탈자커스리전있수대수다퇴를행하사니는습다송할여음을하용을능기스메신보기내자신지시리하대▁instead▁in▁events▁sendholder▁it▁to포▁focus▁focus▁enter▁leave▁and▁function▁place▁the커▁use▁text▁possibleage▁is▁and▁the▁tomess▁send▁the▁windows▁remove전수있다▁set▁order니사습▁toEM_SETCUEBANNER우리를 위해 그 일을 하기 위해 우리의 텍스트 상자에 메시지.

이 작업은 두 가지 간단한 단계로 수행할 수 있습니다. 먼 Windows 노야 합니다를 .SendMessage기능.

private const int EM_SETCUEBANNER = 0x1501;

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)]string lParam);

그런 다음 텍스트 상자의 핸들을 사용하여 메소드, EM_SETCUEBANNER의 값 및 설정할 텍스트를 호출합니다.

SendMessage(textBox1.Handle, EM_SETCUEBANNER, 0, "Username");
SendMessage(textBox2.Handle, EM_SETCUEBANNER, 0, "Password");

참조:텍스트 상자(큐 텍스트)에 대한 자리 표시자 텍스트 설정

이 클래스를 프로젝트에 추가하고 솔루션을 구축합니다.시각적 스튜디오에서 도구 상자를 클릭하면 PlaceholderTextBox라는 새 텍스트 상자 구성 요소가 나타납니다.양식 설계에서 현재 텍스트 상자를 삭제하고 플레이스홀더 텍스트 상자로 대체합니다.

여기에 이미지 설명 입력

PlaceHolderTextBox에 PlaceHolderText 속성이 있습니다.원하는 문자를 설정하고 좋은 하루 보내세요 :)

public class PlaceHolderTextBox : TextBox
{

    bool isPlaceHolder = true;
    string _placeHolderText;
    public string PlaceHolderText
    {
        get { return _placeHolderText; }
        set
        {
            _placeHolderText = value;
            setPlaceholder();
        }
    }

    public new string Text
    {
        get => isPlaceHolder ? string.Empty : base.Text;
        set => base.Text = value;
    }

    //when the control loses focus, the placeholder is shown
    private void setPlaceholder()
    {
        if (string.IsNullOrEmpty(base.Text))
        {
            base.Text = PlaceHolderText;
            this.ForeColor = Color.Gray;
            this.Font = new Font(this.Font, FontStyle.Italic);
            isPlaceHolder = true;
        }
    }

    //when the control is focused, the placeholder is removed
    private void removePlaceHolder()
    {

        if (isPlaceHolder)
        {
            base.Text = "";
            this.ForeColor = System.Drawing.SystemColors.WindowText;
            this.Font = new Font(this.Font, FontStyle.Regular);
            isPlaceHolder = false;
        }
    }
    public PlaceHolderTextBox()
    {
        GotFocus += removePlaceHolder;
        LostFocus += setPlaceholder;
    }

    private void setPlaceholder(object sender, EventArgs e)
    {
        setPlaceholder();
    }

    private void removePlaceHolder(object sender, EventArgs e)
    {
        removePlaceHolder();
    }
}

이건 내 코드가 아니지만, 자주 사용하고 완벽하게 작동합니다.XAML 전용

<TextBox x:Name="Textbox" Height="23" Margin="0,17,18.8,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" HorizontalAlignment="Right" ></TextBox>

<TextBlock x:Name="Placeholder" IsHitTestVisible="False" TextWrapping="Wrap" Text="Placeholder Text" VerticalAlignment="Top" Margin="0,20,298.8,0" Foreground="DarkGray" HorizontalAlignment="Right" Width="214">
  <TextBlock.Style>
    <Style TargetType="{x:Type TextBlock}">
      <Setter Property="Visibility" Value="Collapsed"/>
      <Style.Triggers>
        <DataTrigger Binding="{Binding Text, ElementName=Textbox}" Value="">
          <Setter Property="Visibility" Value="Visible"/>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </TextBlock.Style>
</TextBlock>

구조에 연결된 속성:

public static class TextboxExtensions
{
    public static readonly DependencyProperty PlaceholderProperty = 
        DependencyProperty.RegisterAttached(
            "Placeholder", 
            typeof(string), 
            typeof(TextboxExtensions), 
            new PropertyMetadata(default(string), propertyChangedCallback: PlaceholderChanged)
            );

    private static void PlaceholderChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {
        var tb = dependencyObject as TextBox;

        if (tb == null)
            return;

        tb.LostFocus -= OnLostFocus;
        tb.GotFocus -= OnGotFocus;

        if (args.NewValue != null)
        {
            tb.GotFocus += OnGotFocus;
            tb.LostFocus += OnLostFocus;
        }

        SetPlaceholder(dependencyObject, args.NewValue as string);

        if (!tb.IsFocused)
            ShowPlaceholder(tb);
    }

    private static void OnLostFocus(object sender, RoutedEventArgs routedEventArgs)
    {
        ShowPlaceholder(sender as TextBox);
    }

    private static void OnGotFocus(object sender, RoutedEventArgs routedEventArgs)
    {
        HidePlaceholder(sender as TextBox);
    }

    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static void SetPlaceholder(DependencyObject element, string value)
    {
        element.SetValue(PlaceholderProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static string GetPlaceholder(DependencyObject element)
    {
        return (string)element.GetValue(PlaceholderProperty);
    }

    private static void ShowPlaceholder(TextBox textBox)
    {
        if (string.IsNullOrWhiteSpace(textBox.Text))
        {
            textBox.Text = GetPlaceholder(textBox);
        }
    }

    private static void HidePlaceholder(TextBox textBox)
    {
        string placeholderText = GetPlaceholder(textBox);

        if (textBox.Text == placeholderText)
            textBox.Text = string.Empty;
    }
}

용도:

<TextBox Text="hi" local:TextboxExtensions.Placeholder="Hello there"></TextBox>

EM_SETCUEBANNER메시지가 가장 단순할 수 있습니다. 한 가지 마음에 들지 않는 것은 컨트롤에 포커스가 걸리면 자리 표시자 텍스트가 사라집니다.그것은 제가 양식을 작성할 때의 불만입니다.필드가 무엇을 위한 것인지 기억하기 위해 클릭을 해야 합니다.

여기 WinForms를 위한 또 다른 솔루션이 있습니다.위에 표시됩니다.Label사용자가 입력을 시작할 때만 사라지는 컨트롤의 맨 위에 있습니다.

그것은 확실히 방탄이 아닙니다.모든 것을 허용합니다.Control하지만 난 단지 테스트를 했을 뿐입니다.TextBox일부 컨트롤에서 작동하려면 수정이 필요할 수 있습니다.는 메는다반니다합환을을 합니다.Label특정한 경우에 약간의 수정이 필요한 경우에 대비하여 제어할 수 있지만, 절대 필요하지 않을 수 있습니다.

다음과 같이 사용합니다.

SetPlaceholder(txtSearch, "Type what you're searching for");

방법은 다음과 같습니다.

/// <summary>
/// Sets placeholder text on a control (may not work for some controls)
/// </summary>
/// <param name="control">The control to set the placeholder on</param>
/// <param name="text">The text to display as the placeholder</param>
/// <returns>The newly-created placeholder Label</returns>
public static Label SetPlaceholder(Control control, string text) {
    var placeholder = new Label {
        Text = text,
        Font = control.Font,
        ForeColor = Color.Gray,
        BackColor = Color.Transparent,
        Cursor = Cursors.IBeam,
        Margin = Padding.Empty,

        //get rid of the left margin that all labels have
        FlatStyle = FlatStyle.System,
        AutoSize = false,

        //Leave 1px on the left so we can see the blinking cursor
        Size = new Size(control.Size.Width - 1, control.Size.Height),
        Location = new Point(control.Location.X + 1, control.Location.Y)
    };

    //when clicking on the label, pass focus to the control
    placeholder.Click += (sender, args) => { control.Focus(); };

    //disappear when the user starts typing
    control.TextChanged += (sender, args) => {
        placeholder.Visible = string.IsNullOrEmpty(control.Text);
    };

    //stay the same size/location as the control
    EventHandler updateSize = (sender, args) => {
        placeholder.Location = new Point(control.Location.X + 1, control.Location.Y);
        placeholder.Size = new Size(control.Size.Width - 1, control.Size.Height);
    };

    control.SizeChanged += updateSize;
    control.LocationChanged += updateSize;

    control.Parent.Controls.Add(placeholder);
    placeholder.BringToFront();

    return placeholder;
}

ExceptionLimeCat의 답변을 기반으로 한 개선 사항:

Color farbe;
string ph = "Placeholder-Text";

private void Form1_Load(object sender, EventArgs e)
{
    farbe = myTxtbx.ForeColor;
    myTxtbx.GotFocus += RemoveText;
    myTxtbx.LostFocus += AddText;
    myTxtbx.Text = ph;
}


public void RemoveText(object sender, EventArgs e)
{
    myTxtbx.ForeColor = farbe;
    if (myTxtbx.Text == ph)
        myTxtbx.Text = "";
}

public void AddText(object sender, EventArgs e)
{
    if (String.IsNullOrWhiteSpace(myTxtbx.Text))
    {
        myTxtbx.ForeColor = Color.Gray;
        myTxtbx.Text = ph;
    }
}

이것이 오래된 실인 것은 알지만, .NET 코어 » 5은 NET 5.0을 했습니다.TextBox.PlaceholderText소유물.

https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.textbox.placeholdertext?view=net-5.0

이는 로그인과 같은 작업을 수행할 수 있는 단추가 있음을 의미합니다.작업을 수행하기 전에 텍스트 상자가 채워졌는지 확인합니다.그렇지 않으면 텍스트를 대체합니다.

 private void button_Click(object sender, EventArgs e)
 {
     string textBoxText = textBox.Text;

     if (String.IsNullOrWhiteSpace(textBoxText))
     {
         textBox.Text = "Fill in the textbox";
     }
 }

 private void textBox_Enter(object sender, EventArgs e)
 {
     TextBox currentTextbox = sender as TextBox;
     if (currentTextbox.Text == "Fill in the textbox")
     {
         currentTextbox.Text = "";
     }
 }

좀 유치하지만 당신이 주는 가치에 대한 텍스트를 확인하는 것이 제가 할 수 있는 최선의 방법입니다. 더 나은 해결책을 얻기 위해 c#을 잘 하는 것은 아닙니다.

기본값을 가져올있습니다. 위에 겹쳐서 수정할 수 있습니다.TextBlock그리고 사용합니다.Style숨김 및 올바른 상태로 표시하는 트리거를 추가합니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace App_name
{
   public class CustomTextBox : TextBox
    {
        private string Text_ = "";
        public CustomTextBox() : base()
        {}

        public string setHint
        {
            get { return Text_; }
            set { Text_ = value; }
        }
        protected override void OnGotFocus(RoutedEventArgs e)
        {
            base.OnGotFocus(e);
            if (Text_.Equals(this.Text))
                this.Clear();
        }
        protected override void OnLostFocus(RoutedEventArgs e)
        {
            base.OnLostFocus(e);
            if (String.IsNullOrWhiteSpace(this.Text))
                this.Text = Text_;
        }
    }
}
>    xmlns:local="clr-namespace:app_name"
>  <local:CustomTextBox
>                 x:Name="id_number_txt"
>                 Width="240px"
>                 Height="auto"/>

@Kemal Karadag에서 영감을 얻은 솔루션을 소개합니다.

여기에 게시된 모든 해결책이 초점에 의존하고 있다는 것을 알게 되었습니다.

저는 제 자리 표시자가 구글 크롬의 표준 HTML 자리 표시자의 정확한 복제자가 되기를 원했습니다.

상자가 초점을 맞출 때 자리 표시자를 숨기거나 표시하는 대신,

상자의 텍스트 길이에 따라 자리 표시자를 숨기거나 표시합니다.

상자가 비어 있으면 자리 표시자가 표시되고 상자에 입력하면 자리 표시자가 사라집니다.

표준 텍스트 상자에서 상속되므로 도구 상자에서 찾을 수 있습니다!

using System;
using System.Drawing;
using System.Windows.Forms;

public class PlaceHolderTextBox : TextBox
{
    private bool isPlaceHolder = true;
    private string placeHolderText;

    public string PlaceHolderText
    {
        get { return placeHolderText; }
        set
        {
            placeHolderText = value;
            SetPlaceholder();
        }
    }

    public PlaceHolderTextBox()
    {
        TextChanged += OnTextChanged;
    }

    private void SetPlaceholder()
    {
        if (!isPlaceHolder)
        {
            this.Text = placeHolderText;
            this.ForeColor = Color.Gray;
            isPlaceHolder = true;
        }
    }

    private void RemovePlaceHolder()
    {
        if (isPlaceHolder)
        {
            this.Text = this.Text[0].ToString(); // Remove placeHolder text, but keep the character we just entered
            this.Select(1, 0); // Place the caret after the character we just entered
            this.ForeColor = System.Drawing.SystemColors.WindowText;
            isPlaceHolder = false;
        }
    }

    private void OnTextChanged(object sender, EventArgs e)
    {
        if (this.Text.Length == 0)
        {
            SetPlaceholder();
        }
        else
        {
            RemovePlaceHolder();
        }
    }
}

이것은 텍스트 상자의 확장 방법입니다.자리 표시자 텍스트를 프로그래밍 방식으로 추가합니다.

myTextBox.AddPlaceholderText("Hello World!");

확장 방법:

public static void AddPlaceholderText(this TextBox textBox, string placeholderText)
        {
            if (string.IsNullOrWhiteSpace(textBox.Text))
                textBox.Text = placeholderText;
            textBox.SetResourceReference(Control.ForegroundProperty,
                textBox.Text != placeholderText
                    ? "SystemControlForegroundBaseHighBrush"
                    : "SystemControlForegroundBaseMediumBrush");
            var ignoreSelectionChanged = false;
            textBox.SelectionChanged += (sender, args) =>
            {
                if (ignoreSelectionChanged) { ignoreSelectionChanged = false; return; }
                if (textBox.Text != placeholderText) return;
                ignoreSelectionChanged = true;
                textBox.Select(0, 0);
            };
            var lastText = textBox.Text;
            var ignoreTextChanged = false;
            textBox.TextChanged += (sender, args) =>
            {
                if (ignoreTextChanged) { ignoreTextChanged = false; return; }
                if (string.IsNullOrWhiteSpace(textBox.Text))
                {
                    ignoreTextChanged = true;
                    textBox.Text = placeholderText;
                    textBox.Select(0, 0);
                }
                else if (lastText == placeholderText)
                {
                    ignoreTextChanged = true;
                    textBox.Text = textBox.Text.Substring(0, 1);
                    textBox.Select(1, 0);
                }

                textBox.SetResourceReference(Control.ForegroundProperty,
                    textBox.Text != placeholderText
                        ? "SystemControlForegroundBaseHighBrush"
                        : "SystemControlForegroundBaseMediumBrush");
                lastText = textBox.Text;
            };
        }

해피 코딩, BierDav

텍스트 상자 이름을 자리 표시자로 사용할 의향이 있었기 때문에 저에게 맞는 방법을 생각해 냈습니다.아래를 참조하십시오.

public TextBox employee = new TextBox();

private void InitializeHomeComponent()
{
    //
    //employee
    //
    this.employee.Name = "Caller Name";
    this.employee.Text = "Caller Name";
    this.employee.BackColor = System.Drawing.SystemColors.InactiveBorder;
    this.employee.Location = new System.Drawing.Point(5, 160);
    this.employee.Size = new System.Drawing.Size(190, 30);
    this.employee.TabStop = false;
    this.Controls.Add(employee);
    // I loop through all of my textboxes giving them the same function
    foreach (Control C in this.Controls)
    {
        if (C.GetType() == typeof(System.Windows.Forms.TextBox))
        {
            C.GotFocus += g_GotFocus;
            C.LostFocus += g_LostFocus;
        }
     }
 }

    private void g_GotFocus(object sender, EventArgs e)
    {
        var tbox = sender as TextBox;
        tbox.Text = "";
    }

    private void g_LostFocus(object sender, EventArgs e)
    {
        var tbox = sender as TextBox;
        if (tbox.Text == "")
        {
            tbox.Text = tbox.Name;
        }
    }

다음 코드를 사용해 보십시오.

<TextBox x:Name="InvoiceDate" Text="" Width="300"  TextAlignment="Left" Height="30" Grid.Row="0" Grid.Column="3" Grid.ColumnSpan="2" />
                    <TextBlock IsHitTestVisible="False" Text="Men att läsa" Width="300"  TextAlignment="Left" Height="30" Grid.Row="0" Grid.Column="3" Grid.ColumnSpan="2" Padding="5, 5, 5, 5"  Foreground="LightGray">
                        <TextBlock.Style>
                            <Style TargetType="{x:Type TextBlock}">
                                <Setter Property="Visibility" Value="Collapsed"/>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Text, ElementName=InvoiceDate}" Value="">
                                        <Setter Property="Visibility" Value="Visible"/>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding ElementName=InvoiceDate, Path=IsFocused}" Value="True">
                                        <Setter Property="Visibility" Value="Collapsed"/>
                                    </DataTrigger>

                                </Style.Triggers>
                            </Style>
                        </TextBlock.Style>
                    </TextBlock>

마우스를 클릭할 때 플레이스홀더 텍스트가 "User_Name"이라고 가정합니다.

 private void textBox1_MouseClick(object sender, MouseEventArgs e)
 {
     if(textBox1.Text == "User_Name")
          textBox1.Text = "";
 }
    public void Initialize()
    {
        SetPlaceHolder(loginTextBox, " Логин ");
        SetPlaceHolder(passwordTextBox, " Пароль ");
    }

    public void SetPlaceHolder(Control control, string PlaceHolderText)
    {
        control.Text = PlaceHolderText;
        control.GotFocus += delegate(object sender, EventArgs args) {
            if (control.Text == PlaceHolderText)
            {
                control.Text = "";
            }
        };
        control.LostFocus += delegate(object sender, EventArgs args){
            if (control.Text.Length == 0)
            {
                control.Text = PlaceHolderText;
            }
        };
    }

를 사용하는 대신.TextBox의 텍스트 속성을 자리 표시자로 텍스트 블록을 오버레이했습니다.사용할 수 없었습니다.이벤트에 바인딩되었기 때문에 텍스트 속성입니다.

XAML:

<Canvas Name="placeHolderCanvas">
    <TextBox  AcceptsReturn="True" Name="txtAddress" Height="50" Width="{Binding ActualWidth, ElementName=placeHolderCanvas}"
              Tag="Please enter your address"/>
</Canvas>

VB.NET

Public Shared Sub InitPlaceholder(canvas As Canvas)
    Dim txt As TextBox = canvas.Children.OfType(Of TextBox).First()
    Dim placeHolderLabel = New TextBlock() With {.Text = txt.Tag,
                                                 .Foreground = New SolidColorBrush(Color.FromRgb(&H77, &H77, &H77)),
                                                 .IsHitTestVisible = False}
    Canvas.SetLeft(placeHolderLabel, 3)
    Canvas.SetTop(placeHolderLabel, 1)
    canvas.Children.Add(placeHolderLabel)
    AddHandler txt.TextChanged, Sub() placeHolderLabel.Visibility = If(txt.Text = "", Visibility.Visible, Visibility.Hidden)
End Sub

결과:

당신은 또한 이런 방법으로 시도할 수 있습니다.

함수를 호출합니다.

TextboxPlaceHolder(this.textBox1, "YourPlaceHolder");

이 함수를 씁니다.

private void TextboxPlaceHolder(Control control, string PlaceHolderText)
{
        control.Text = PlaceHolderText;
        control.GotFocus += delegate (object sender, EventArgs args)
        {
            if (cusmode == false)
            {
                control.Text = control.Text == PlaceHolderText ? string.Empty : control.Text;
                //IF Focus TextBox forecolor Black
                control.ForeColor = Color.Black;
            }
        };

        control.LostFocus += delegate (object sender, EventArgs args)
        {
            if (string.IsNullOrWhiteSpace(control.Text) == true)
            {
                control.Text = PlaceHolderText;
                //If not focus TextBox forecolor to gray
                control.ForeColor = Color.Gray;
            }

        };
}

더 나은 해결책이 있지만 가장 쉬운 해결책은 여기에 있습니다. 텍스트 상자 텍스트를 원하는 문자열로 설정한 다음 텍스트 상자를 삭제하는 기능을 만들고 텍스트 상자에서 해당 기능을 실행합니다. 포커스 입력 이벤트

재사용 가능한 사용자 정의 컨트롤을 작성했습니다. 프로젝트에서 여러 자리 표시자 텍스트 상자를 구현해야 하는 사용자에게 도움이 될 수 있습니다.
다음은 인스턴스의 구현 예가 있는 사용자 지정 클래스입니다. VS를 사용하여 이 코드를 새 Winforms 프로젝트에 붙여넣으면 쉽게 테스트할 수 있습니다.

namespace reusebleplaceholdertextbox
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // implementation
            CustomPlaceHolderTextbox myCustomTxt = new CustomPlaceHolderTextbox(
                "Please Write Text Here...", Color.Gray, new Font("ARIAL", 11, FontStyle.Italic)
                , Color.Black, new Font("ARIAL", 11, FontStyle.Regular)
                );

            myCustomTxt.Multiline = true;
            myCustomTxt.Size = new Size(200, 50);
            myCustomTxt.Location = new Point(10, 10);
            this.Controls.Add(myCustomTxt);
        }
    }

    class CustomPlaceHolderTextbox : System.Windows.Forms.TextBox
    {
        public string PlaceholderText { get; private set; }
        public Color PlaceholderForeColor { get; private set; }
        public Font PlaceholderFont { get; private set; }

        public Color TextForeColor { get; private set; }
        public Font TextFont { get; private set; }

        public CustomPlaceHolderTextbox(string placeholdertext, Color placeholderforecolor,
            Font placeholderfont, Color textforecolor, Font textfont)
        {
            this.PlaceholderText = placeholdertext;
            this.PlaceholderFont = placeholderfont;
            this.PlaceholderForeColor = placeholderforecolor;
            this.PlaceholderFont = placeholderfont;
            this.TextForeColor = textforecolor;
            this.TextFont = textfont;
            if (!string.IsNullOrEmpty(this.PlaceholderText))
            {
                SetPlaceHolder(true);
                this.Update();
            }
        }

        private void SetPlaceHolder(bool addEvents)
        {
            if (addEvents)
            {  
                this.LostFocus += txt_lostfocus;
                this.Click += txt_click;
            }

            this.Text = PlaceholderText;
            this.ForeColor = PlaceholderForeColor;
            this.Font = PlaceholderFont;
        }

        private void txt_click(object sender, EventArgs e)
        {
            // IsNotFirstClickOnThis:
            // if there is no other control in the form
            // we will have a problem after the first load
            // because we dont other focusable control to move the focus to
            // and we dont want to remove the place holder
            // only on first time the place holder will be removed by click event
            RemovePlaceHolder();
            this.GotFocus += txt_focus;
            // no need for this event listener now
            this.Click -= txt_click;
        }

        private void RemovePlaceHolder()
        {
            this.Text = "";
            this.ForeColor = TextForeColor;
            this.Font = TextFont;
        }
        private void txt_lostfocus(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(this.Text))
            {
                // set placeholder again
                SetPlaceHolder(false);
            }
        }

        private void txt_focus(object sender, EventArgs e)
        {
            if (this.Text == PlaceholderText)
            {
                // IsNotFirstClickOnThis:
                // if there is no other control in the form
                // we will have a problem after the first load
                // because we dont other focusable control to move the focus to
                // and we dont want to remove the place holder
                RemovePlaceHolder();
            }
        }
    }
}

PlcaeHoldText 및 PlaceHoldBackround를 사용하여 TextBox를 확장합니다.제 프로젝트에서 코드를 빼냈습니다.

Grid or Canvas에게 작별 인사!

<TextBox x:Class="VcpkgGui.View.PlaceHoldedTextBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:VcpkgGui.View"
             mc:Ignorable="d"
             Name="placeHoldTextBox"
             TextAlignment="Left"
         >
    <TextBox.Resources>
        <local:FrameworkWidthConverter x:Key="getElemWidth"/>
        <local:FrameworkHeightConverter x:Key="getElemHeight"/>
        <VisualBrush x:Key="PlaceHoldTextBrush" TileMode="None" Stretch="None" AlignmentX="Left" AlignmentY="Center" Opacity="1">
            <VisualBrush.Visual>
                <Border Background="{Binding ElementName=placeHoldTextBox, Path=PlaceHoldBackground}"
                        BorderThickness="0"
                        Margin="0,0,0,0"
                        Width="{Binding Mode=OneWay, ElementName=placeHoldTextBox, Converter={StaticResource getElemWidth}}"
                        Height="{Binding Mode=OneWay, ElementName=placeHoldTextBox, Converter={StaticResource getElemHeight}}"
                        >
                    <Label Content="{Binding ElementName=placeHoldTextBox, Path=PlaceHoldText}"
                           Background="Transparent"
                           Foreground="#88000000"
                           HorizontalAlignment="Stretch"
                           VerticalAlignment="Stretch"
                           HorizontalContentAlignment="Left"
                           VerticalContentAlignment="Center"
                           ClipToBounds="True"
                           Padding="0,0,0,0"
                           FontSize="14"
                           FontStyle="Normal"
                           Opacity="1"/>
                </Border>
            </VisualBrush.Visual>
        </VisualBrush>
    </TextBox.Resources>
    <TextBox.Style>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Text" Value="{x:Null}">
                    <Setter Property="Background"  Value="{StaticResource PlaceHoldTextBrush}"/>
                </Trigger>
                <Trigger Property="Text" Value="">
                    <Setter Property="Background"  Value="{StaticResource PlaceHoldTextBrush}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
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 VcpkgGui.View
{
    /// <summary>
    /// PlaceHoldedTextBox.xaml 的交互逻辑
    /// </summary>
    public partial class PlaceHoldedTextBox : TextBox
    {

        public string PlaceHoldText
        {
            get { return (string)GetValue(PlaceHoldTextProperty); }
            set { SetValue(PlaceHoldTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PlaceHolderText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PlaceHoldTextProperty =
            DependencyProperty.Register("PlaceHoldText", typeof(string), typeof(PlaceHoldedTextBox), new PropertyMetadata(string.Empty));



        public Brush PlaceHoldBackground
        {
            get { return (Brush)GetValue(PlaceHoldBackgroundProperty); }
            set { SetValue(PlaceHoldBackgroundProperty, value); }
        }

        public static readonly DependencyProperty PlaceHoldBackgroundProperty =
            DependencyProperty.Register(nameof(PlaceHoldBackground), typeof(Brush), typeof(PlaceHoldedTextBox), new PropertyMetadata(Brushes.White));

        public PlaceHoldedTextBox() :base()
        {
            InitializeComponent();
        }
    }

    [ValueConversion(typeof(FrameworkElement), typeof(double))]
    internal class FrameworkWidthConverter : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if(value is FrameworkElement elem)
                return double.IsNaN(elem.Width) ? elem.ActualWidth : elem.Width;
            else
                return DependencyProperty.UnsetValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return DependencyProperty.UnsetValue;
        }
    }

    [ValueConversion(typeof(FrameworkElement), typeof(double))]
    internal class FrameworkHeightConverter : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is FrameworkElement elem)
                return double.IsNaN(elem.Height) ? elem.ActualHeight : elem.Height;
            else
                return DependencyProperty.UnsetValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return DependencyProperty.UnsetValue;
        }
    }

}

txtUsuario.특성.추가("자리 표시자", "텍스트");

Windows Forms TextBox 컨트롤을 위한 매우 효과적인 솔루션입니다.(XAML에 대한 확신 없음).

다중 회선 모드에서도 작동합니다.

아마도 ComboBox 컨트롤(선택하지 않음)과 같은 다른 컨트롤을 위해 확장될 수 있습니다.

매력적으로 작동합니다.

public class WTextBox : TextBox
{
    private string _placeholder;


    [Category("Appearance")]
    public string Placeholder
    {
        get { return _placeholder; }
        set
        {
            _placeholder = value ?? string.Empty;
            Invalidate();
        }
    }

    public WTextBox()
    {
        _placeholder = string.Empty;
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        if (m.Msg != 0xF || Focused || !string.IsNullOrEmpty(Text) || string.IsNullOrWhiteSpace(_placeholder))
        {
            return;
        }

        using (var g = CreateGraphics())
        {
            TextRenderer.DrawText(g, _placeholder, Font, ClientRectangle, SystemColors.GrayText, BackColor, TextFormatFlags.Left);
        }
    }
}

언급URL : https://stackoverflow.com/questions/11873378/adding-placeholder-text-to-textbox

반응형