WPF 基本コントロールの PasswordBox スタイル

WPF 基本コントロールの PasswordBox スタイル

基本コントロール

最終更新 2022/05/05 6:49
驚鏵 WPF开发者
読了目安 4 分
カテゴリ
WPF
タグ
.NET WPF

その他の基本コントロール

  1. Window
  2. Button
  3. CheckBox
  4. ComboBox
  5. DataGrid
  6. DatePicker
  7. Expander
  8. GroupBox
  9. ListBox
  10. ListView
  11. Menu

PasswordBox で以下の効果を実現する

01 — コードは以下の通り

  1. PasswordBox はウォーターマークをサポートしていないため、DependencyObject添付プロパティを使用してウォーターマークを実現する必要があります。
public class ElementHelper : DependencyObject
{
    public static string GetWatermark(DependencyObject obj)
    {
        return (string)obj.GetValue(WatermarkProperty);
    }

    public static void SetWatermark(DependencyObject obj, string value)
    {
        obj.SetValue(WatermarkProperty, value);
    }

    public static readonly DependencyProperty WatermarkProperty =
        DependencyProperty.RegisterAttached("Watermark", typeof(string), typeof(ElementHelper), new PropertyMetadata("Please input"));

}
  1. 名前空間 xmlns:wpfs="clr-namespace:WPFDevelopers.Minimal.Helpers" をインポートします。
<TextBlock
  x:Name="PART_TextBlockWatermark"
  Text="{Binding Path=(wpfs:ElementHelper.Watermark),RelativeSource={RelativeSource TemplatedParent}}"
  Foreground="{StaticResource RegularTextSolidColorBrush}"
  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
  FontSize="{StaticResource NormalFontSize}"
  Margin="7.5,0"
  Visibility="Collapsed"
/>
  1. ウォーターマークの設定が完了したら、次にパスワードボックスの内容が空の場合にウォーターマークを表示するために、追加のクラス PasswordBoxHelper を作成します。
public class PasswordBoxHelper : 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(PasswordBoxHelper), 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(PasswordBoxHelper), 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);
    }
}
  1. XAML で添付プロパティ PasswordLength0 の場合にウォーターマークを表示するよう判断します。
<Trigger Property="wpfs:PasswordBoxHelper.PasswordLength" Value="0">
  <Setter
    Property="Visibility"
    TargetName="PART_TextBlockWatermark"
    Value="Visible"
  />
</Trigger>
  1. Styles.PasswordBox.xaml のコードは以下の通りです。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:wpfs="clr-namespace:WPFDevelopers.Minimal.Helpers">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="../Themes/Basic/ControlBasic.xaml"/>
        <ResourceDictionary Source="../Themes/Basic/Animations.xaml"/>
    </ResourceDictionary.MergedDictionaries>

    <Style TargetType="{x:Type PasswordBox}" BasedOn="{StaticResource ControlBasicStyle}">
        <Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="PasswordChar" Value="●" />
        <Setter Property="MinHeight" Value="{StaticResource MinHeight}" />
        <Setter Property="MinWidth" Value="180"/>
        <Setter Property="AllowDrop" Value="True" />
        <Setter Property="Cursor" Value="Hand"/>
        <Setter Property="Padding" Value="6,0"/>
        <Setter Property="wpfs:PasswordBoxHelper.IsMonitoring" Value="True"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type PasswordBox}">
                    <Border x:Name="PART_Border"
                            CornerRadius="{Binding Path=(wpfs:ElementHelper.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}"
                            BorderThickness="1"
                            Width="{TemplateBinding Width}"
                            Height="{TemplateBinding Height}">
                        <Border.Background>
                            <SolidColorBrush Color="{DynamicResource WhiteColor}" />
                        </Border.Background>
                        <Border.BorderBrush>
                            <SolidColorBrush Color="{DynamicResource BaseColor}" />
                        </Border.BorderBrush>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="Disabled" />
                                <VisualState x:Name="MouseOver" >
                                    <Storyboard>
                                        <ColorAnimation Duration="00:00:0.3"
                                                        Storyboard.TargetName="PART_Border"
                                                        Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
                                                        To="{StaticResource PrimaryNormalColor}"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <!--<ScrollViewer x:Name="PART_ContentHost" />-->
                        <Grid Margin="{TemplateBinding Padding}">
                            <ScrollViewer x:Name="PART_ContentHost" />
                            <TextBlock x:Name="PART_TextBlockWatermark"
                                Text="{Binding Path=(wpfs:ElementHelper.Watermark),RelativeSource={RelativeSource TemplatedParent}}"
                                Foreground="{StaticResource RegularTextSolidColorBrush}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                FontSize="{StaticResource NormalFontSize}"
                                Margin="7.5,0" Visibility="Collapsed"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="wpfs:PasswordBoxHelper.PasswordLength" Value="0">
                            <Setter Property="Visibility" TargetName="PART_TextBlockWatermark" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>
  1. Styles.PasswordBox.xaml のコードは以下の通りです。
<WrapPanel Margin="0,10">
  <PasswordBox />
  <PasswordBox Margin="10,0" ws:ElementHelper.Watermark="パスワードを入力してください" />
  <PasswordBox IsEnabled="False" />
</WrapPanel>

02 — 効果プレビュー

さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2025/09/13

WPF から Avalonia への移行シリーズ:なぜ WPF プログラムを Avalonia に移行しなければならないのか

過去数年間、当社の上位機ソフトウェアは主に WPF と WinForm で開発されてきました。これらの技術は Windows プラットフォームで非常に便利であり、小規模試作から現在の規模拡大による納品まで、私たちを支えてきました。しかし、ビジネスの発展や顧客ニーズの変化に伴い、単一の Windows テクノロジースタックは私たちが必ず乗り越えなければならない壁となってきました。

続きを読む
同じカテゴリ / 同じタグ 2025/01/26

WPF カスタムXMLファイルによる国際化

この記事では、WPFプログラムでカスタムXMLファイルを使用して国際化を実現する方法について詳しく説明します。必要なNuGetパッケージのインストール、言語リストの動的取得、言語の動的切り替え、コードおよびXAMLインターフェースでの翻訳文字列の使用などを含み、ソースコードのリンクも提供し、開発者がWPFアプリケーションの国際化を簡単に実装できるように支援します。

続きを読む