[C#] 텍스트 상자에 자리 표시 자 텍스트 추가

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 SendMessage 함수를 사용하여 EM_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");

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


답변

이 클래스를 프로젝트에 추가하고 솔루션을 빌드하십시오. Visual Studio에서 도구 상자를 클릭하면 PlaceholderTextBox라는 새 텍스트 상자 구성 요소가 표시됩니다. 양식 디자인에서 현재 텍스트 상자를 삭제하고 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컨트롤 위에 a 를 오버레이 하여 사용자가 입력을 시작할 때만 사라집니다.

확실히 방탄은 아닙니다. 그것은 모든 것을 받아들이지 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;
}