Водяной знак WPF PasswordBox от водяного знака TextBox

путь, упомянутый @dirkgently ( v.begin() + index ), хорошим и быстрым для векторов

, но std::advance ( v.begin(), index ) большая часть универсального пути и для итераторов произвольного доступа, работает постоянное время также.

РЕДАКТИРОВАНИЕ
различия в использовании:

std::vector<>::iterator it = ( v.begin() + index );

или

std::vector<>::iterator it = v.begin();
std::advance( it, index );

добавленный после @litb примечания.

5
задан Community 23 May 2017 в 12:34
поделиться

2 ответа

Общий подход такой же: вы пишете собственный стиль управления и показываете водяной знак всякий раз, когда поле пароля пусто. Единственная проблема здесь в том, что свойство PasswordBox.Password не является свойством зависимости, и вы не можете использовать его в триггере. Кроме того, PasswordBox запечатан, поэтому вы не можете переопределить это поведение уведомления. Но здесь вы можете использовать вложенные свойства. В следующем коде показано, как это сделать.

XAML

<Window x:Class="WpfTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WpfTest="clr-namespace:WpfTest"
    Title="Password Box Sample" Height="300" Width="300">
  <Window.Resources>
    <Style x:Key="{x:Type PasswordBox}"
        TargetType="{x:Type PasswordBox}">
      <Setter Property="WpfTest:PasswordBoxMonitor.IsMonitoring"
              Value="True"/>
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type PasswordBox}">
            <Border Name="Bd"
                    Background="{TemplateBinding Background}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    SnapsToDevicePixels="true">
              <Grid>
                <ScrollViewer x:Name="PART_ContentHost"
                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                <TextBlock Text="Please enter your password" 
                           Margin="4, 2, 0, 0"
                           Foreground="Gray" 
                           Visibility="Collapsed"
                           Name="txtPrompt" />
              </Grid>
            </Border>
            <ControlTemplate.Triggers>
              <Trigger Property="IsEnabled"
                                         Value="false">
                <Setter TargetName="Bd"
                                            Property="Background"
                                            Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                <Setter Property="Foreground"
                                            Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
              </Trigger>
              <Trigger Property="WpfTest:PasswordBoxMonitor.PasswordLength" Value="0">
                <Setter Property="Visibility" TargetName="txtPrompt" Value="Visible"/>
              </Trigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Window.Resources>
  <Grid>
    <PasswordBox VerticalAlignment="Top"/>
  </Grid>
</Window>

C #

using System.Windows;
using System.Windows.Controls;

namespace WpfTest
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

    }

  public class PasswordBoxMonitor : DependencyObject
  {
    public static bool GetIsMonitoring(DependencyObject obj)
    {
      return (bool)obj.GetValue(IsMonitoringProperty);
    }

    public static void SetIsMonitoring(DependencyObject obj, bool value)
    {
      obj.SetValue(IsMonitoringProperty, value);
    }

    public static readonly DependencyProperty IsMonitoringProperty =
        DependencyProperty.RegisterAttached("IsMonitoring", typeof(bool), typeof(PasswordBoxMonitor), new UIPropertyMetadata(false, OnIsMonitoringChanged));



    public static int GetPasswordLength(DependencyObject obj)
    {
      return (int)obj.GetValue(PasswordLengthProperty);
    }

    public static void SetPasswordLength(DependencyObject obj, int value)
    {
      obj.SetValue(PasswordLengthProperty, value);
    }

    public static readonly DependencyProperty PasswordLengthProperty =
        DependencyProperty.RegisterAttached("PasswordLength", typeof(int), typeof(PasswordBoxMonitor), new UIPropertyMetadata(0));

    private static void OnIsMonitoringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      var pb = d as PasswordBox;
      if (pb == null)
      {
        return;
      }
      if ((bool) e.NewValue)
      {
        pb.PasswordChanged += PasswordChanged;
      }
      else
      {
        pb.PasswordChanged -= PasswordChanged;
      }
    }

    static void PasswordChanged(object sender, RoutedEventArgs e)
    {
      var pb = sender as PasswordBox;
      if (pb == null)
      {
        return;
      }
      SetPasswordLength(pb, pb.Password.Length);
    }
  }
}

Обратите внимание на PasswordBoxMonitor в коде XAML.

18
ответ дан 18 December 2019 в 05:43
поделиться

вы можете использовать мой подход для поведения водяного знака. все, что вам нужно сделать, это скопировать и вставить TextBoxWatermarkBehavior и изменить Behavior на Behavior .

вы можете найти демонстрационный проект здесь

4
ответ дан 18 December 2019 в 05:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: