Существует ли стандартное решение для текста водяного знака / заполнителя TextBox в XAML в VS C#. Net Core WPF Application? - PullRequest
0 голосов
/ 07 марта 2020

Итак, я новичок в WPF и XAML, но все, что я пытаюсь сделать, это добавить некоторый текст-заполнитель в TextBox в стандартной форме. Например, «Имя» будет отображаться в текстовом поле при запуске приложения. Когда пользователь щелкает в этом текстовом поле, «Имя» исчезает, и пользователь может свободно вводить свое имя. Если пользователь затем щелкает, ничего не вводя, текст заполнителя появляется снова. Но если бы они начали печатать и , то щелкнули мышью, то, что они набрали, все еще остается и не теряется.

Я думал, что эта функция будет встроена в Visual Studio для TextBoxes или какая-то другая вещь из набора инструментов уже, но если это так, я не могу ее найти. Я перепробовал все виды возни с текстом или содержимым текстового блока и т. Д. c.

Одно решение, которое я нашел не идеальным, заключается в следующем: я создал пользовательский элемент управления с двумя текстовыми полями - один для ввода пользователя и один для текста заполнителя. В зависимости от того, имеет ли пользовательский ввод фокус или текст-заполнитель теряет фокус, текст-заполнитель будет / не будет отображаться. Функциональность верна, но есть еще одна проблема. Я не могу по своему усмотрению изменять заполнитель в моем файле MainWindow.xaml, иначе я теряю возможность даже щелкать текстовое поле в моей форме. Поэтому мне нужно было бы создать пользовательский элемент управления для каждого варианта TextBox, который мне понадобится во всем приложении. Я чувствую, что могу создать пользовательский элемент управления с переменным текстом, но не могу понять, как это сделать.

Это действительно лучшее решение или я могу еще что-то сделать? Я чувствую, что, должно быть, все усложняю, чем на самом деле, но нигде не могу найти лучшего решения.

Мой пользовательский элемент управления xaml файл

<UserControl.Resources>
    <Style TargetType="{x:Type TextBox}">
        <Setter Property="FontFamily" Value="Garamond"/>
    </Style>
</UserControl.Resources>
<Grid>
    <TextBox x:Name="userInput" Height="15.5" HorizontalAlignment="Stretch" LostFocus="userInput_LostFocus"/>
    <TextBox x:Name="waterMarkText" Height="15.5" HorizontalAlignment="Stretch" Text="Search" GotFocus="waterMarkText_GotFocus"/>
</Grid>

Мой пользовательский элемент управления xaml.cs file

private void userInput_LostFocus(object sender, RoutedEventArgs e)
    {
        if (string.IsNullOrEmpty(userInput.Text))
        {
            userInput.Visibility = System.Windows.Visibility.Collapsed;
            waterMarkText.Visibility = System.Windows.Visibility.Visible;

        }
    }

    private void waterMarkText_GotFocus(object sender, RoutedEventArgs e)
    {
        waterMarkText.Visibility = System.Windows.Visibility.Collapsed;
        userInput.Visibility = System.Windows.Visibility.Visible;
        userInput.Focus();
    }

Как использовать пользовательский элемент управления

<local:WMTextBox x:Name="TBFirstName" Grid.Column="2" Grid.Row="2" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Margin="10,0,0,2" 
                         Opacity =" .65" Cursor="IBeam" BorderBrush="Black" BorderThickness="1"/>

Ответы [ 2 ]

1 голос
/ 29 марта 2020

Я все еще довольно нов и у меня была та же проблема, я наткнулся на это после некоторого поиска.

<TextBox PlaceholderText="placeholderString"/>

source https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.textbox.placeholdertext

0 голосов
/ 07 марта 2020

Вы можете полностью повторно шаблонировать элемент управления wpf.

Элементы управления WPF являются «безликими», что означает, что они имеют фиксированное поведение, но не имеют определенного c шаблона. Вы можете заменить шаблон для элемента управления wpf. Это имеет некоторые последствия, которые разработчики, плохо знакомые с wpf, часто не ценят.

Шаблоны обычно go в словаре ресурсов, объединенном в app.xaml. Для быстрой и грязной демонстрации здесь у меня есть шаблон в app.xaml.

         xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
         StartupUri="MainWindow.xaml">
<Application.Resources>
    <ControlTemplate x:Key="WatermarkedTextBoxTemplate" TargetType="{x:Type TextBox}">
        <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
            <Grid>
                <TextBlock x:Name="wm" 
                    Foreground="Gray"
                    Text="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}"
                    FontWeight="Bold" 
                    FontSize="10" FontFamily="Segoe UI" FontStyle="Italic"/>
                <TextBox Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}}">
                    <TextBox.Style>
                        <Style TargetType="{x:Type TextBox}">
                            <Setter Property="Background" Value="White"/>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Path=Text,
                                                               RelativeSource={RelativeSource Self}}" Value="">
                                    <Setter Property="Background" Value="Transparent"/>
                                </DataTrigger>
                                <DataTrigger Binding="{Binding Path=Text,
                                                               RelativeSource={RelativeSource Self}}" Value="{x:Null}">
                                    <Setter Property="Background" Value="Transparent"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBox.Style>
                </TextBox>

            </Grid>
        </Microsoft_Windows_Themes:ListBoxChrome>
        <ControlTemplate.Triggers>
            <Trigger Property="IsEnabled" Value="false">
                <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
</Application.Resources>
</Application>

Выше приведен текстовый блок за текстовым полем. Фон текстового поля скрывает текстовый блок, если текстовое поле имеет какой-либо контент. Текст текстового блока привязан к тегу шаблонируемого элемента управления.

Как я уже сказал, это быстро и грязно, поэтому я использую Tag, который является существующим свойством зависимостей, которое в некотором роде экономит текстовое окно. Более элегантное решение будет использовать присоединенное свойство для водяного знака или наследовать и расширять.

Вот мое текстовое поле:

    <TextBox x:Name="txtCity" 
             Template="{StaticResource WatermarkedTextBoxTemplate}" 
             Tag="Please Enter First Name" 
             Text="{Binding FirstName, Mode=TwoWay}"  
             />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...