ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 为什么WPF PasswordBox有时会变为空白而有些不是?

2019-06-28 22:51:56  阅读:165  来源: 互联网

标签:c wpf passwordbox


我正在包含一个示例程序:似乎在TabBox进入PasswordBox时,输入文本和Tabbing会导致PasswordBox变为空白.但是双击PasswordBox,输入文本和标签不会.为什么会这样?

编辑:我发现这也发生在TextBox上,因此它不是PasswordBox特有的错误.

重新创建每个方案的步骤:

使密码消失

>单击“新建”.
>单击第一个名称字段.
>输入一些东西
>按TAB键
>输入一些东西
>按TAB键
>按TAB键(是两次Save事件触发)
>输入一些东西
>注意点而不是文本-PasswordBox正在工作!
>按TAB键.
>随着PasswordBox变得空白,让你的朋友惊讶!

使密码不会消失

>单击“新建”.
>单击第一个名称字段.
>输入一些东西
>按TAB键
>输入一些东西
>双击密码字段.
>输入一些东西
>注意点而不是文本-PasswordBox正在工作!
>按TAB键.
>让你的朋友惊艳……等等,PasswordBox不是空白? WTF?

Sample Code:

using System;
using System.Collections.ObjectModel;
namespace WpfApplication1 {
    public sealed class MyData    {
        private ObservableCollection<MyDataRow> dataList;
        public ObservableCollection<MyDataRow> DataList { get { return dataList; } }
        public MyData() { dataList = new ObservableCollection<MyDataRow>(); }
        public void AddBlankRow() { DataList.Add(new MyDataRow(this)); }
    }
    public sealed class MyDataRow     {
        private readonly MyData myData;
        public MyDataRow(MyData myData) { this.myData = myData; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Password { get; set; }
    }
}

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

namespace WpfApplication1 {
    public partial class MainWindow : Window  {
        private MyData Data { get { return (MyData)DataContext; } }

        public MainWindow() { InitializeComponent(); }

        private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)  {
            PasswordBox pb = (PasswordBox)sender;
            if (pb != null) {
                MyDataRow row = pb.DataContext as MyDataRow;
                if (row != null) { row.Password = pb.Password; }
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e) { DataContext = new MyData(); }
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { }
        private void SaveExecute(object sender, ExecutedRoutedEventArgs e) { }
        private void NewExecute(object sender, ExecutedRoutedEventArgs e) { Data.AddBlankRow(); }
        private void CancelExecute(object sender, ExecutedRoutedEventArgs e) { Close(); }
    }
}

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" WindowStartupLocation="CenterScreen" Closing="Window_Closing">
    <Window.CommandBindings>
        <CommandBinding Command="Save" Executed="SaveExecute" />
        <CommandBinding Command="New" Executed="NewExecute" />
        <CommandBinding Command="Close" Executed="CancelExecute" />
    </Window.CommandBindings>
    <Grid Margin="0,10,0,0">
        <DataGrid ItemsSource="{Binding DataList}" ColumnWidth="*" Margin="10,0,9,38" HorizontalAlignment="Stretch" 
                  AutoGenerateColumns="False" GridLinesVisibility="Horizontal"
                  HeadersVisibility="Column" HorizontalGridLinesBrush="LightGray" CanUserReorderColumns="False" Background="White" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name"  Binding="{Binding FirstName}"/>
                <DataGridTextColumn Header="Last Name"  Binding="{Binding LastName}"/>
                <DataGridTemplateColumn Header="Password" >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <PasswordBox PasswordChanged="PasswordBox_PasswordChanged"   BorderThickness="0"
                                     Height="23" HorizontalAlignment="Stretch"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <Button  
            Content="_New" Command="New"
            Width="75" Height="23" Margin="10,10,10,10"
            HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
        <Button 
            Content="_Save" Command="Save"
            IsDefault="True"
            IsEnabled="True"
            Width="75" Height="23" Margin="10,10,91,10"
            HorizontalAlignment="Right" VerticalAlignment="Bottom" />
        <Button
            Content="Cancel" Command="Close"
            IsEnabled="True"
            Width="75" Height="23" Margin="10,10,10,10"
            HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
    </Grid>
</Window>

编辑

使用CellTemplate和EditingCellTemplate的数据模板,
我的工作只是保持一致 – 总是展示一些东西,(在这种情况下是一个椭圆).这样,无论如何,当PasswordBox失去焦点时,它会变回elipse.我认为这比有时看到子弹角色更好,有时看到空白. David Edey的DataGrid_PreparingCellForEdit非常适合解决双标签问题.

这是我的数据模板.

    <Grid.Resources>
        <DataTemplate x:Key="PasswordTemplate" >
            <Label BorderThickness="0" Height="23" HorizontalAlignment="Stretch" Content="..."/>
        </DataTemplate>
        <DataTemplate x:Key="EditingPasswordTemplate" >
            <PasswordBox PasswordChanged="PasswordBox_PasswordChanged"   BorderThickness="0" 
                                 Height="23" HorizontalAlignment="Stretch" />
        </DataTemplate>
    </Grid.Resources>

解决方法:

我相信这个问题与两个独立的模板有关:一个用于编辑(CellEditingTemplate),另一个用于显示(CellTemplate).它的正常方法是使用绑定,并使两个单独的模板都绑定到同一条数据,如:http://msdn.microsoft.com/en-us/library/system.windows.controls.datagridtemplatecolumn.celltemplate(v=vs.110).aspx

但是,当然,出于安全原因,PasswordBox不允许您绑定到密码(因为密码不是依赖属性).如果这不是一个大问题(我不完全理解为什么会这样,但我想他们不希望明文密码在绑定中飞来飞去而人们没有意识到他们正在做什么),那么你可以创建一个绑定每篇文章的后半部分:http://wpftutorial.net/PasswordBox.html – 使用自定义静态依赖项属性.

所以我已经在下面的代码中实现了这个程序,并且我还修复了密码框没有正确聚焦并且需要两个选项卡的错误,通过向PreparingCellForEdit事件添加处理程序,根据https://stackoverflow.com/a/2835464/3940783

总而言之,我的工作示例的示例代码是:

using System;
using System.Collections.ObjectModel;
namespace WpfApplication1 {
    public sealed class MyData    {
        private ObservableCollection<MyDataRow> dataList;
        public ObservableCollection<MyDataRow> DataList { get { return dataList; } }
        public MyData() { dataList = new ObservableCollection<MyDataRow>(); }
        public void AddBlankRow() { DataList.Add(new MyDataRow(this)); }
    }
    public sealed class MyDataRow     {
        private readonly MyData myData;
        public MyDataRow(MyData myData) { this.myData = myData; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Password { get; set; }
    }
}

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace WpfApplication1 {
    public partial class MainWindow : Window
    {
        public MainWindow() { InitializeComponent(); }
        private MyData Data { get { return (MyData)DataContext; } }

        void DataGrid_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
        {
            var inputElement = VisualTreeHelper.GetChild(e.EditingElement, 0) as PasswordBox;
            if (inputElement != null)
            {
                Keyboard.Focus(inputElement);
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e) { DataContext = new MyData(); }
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { }
        private void SaveExecute(object sender, ExecutedRoutedEventArgs e) { }
        private void NewExecute(object sender, ExecutedRoutedEventArgs e) { Data.AddBlankRow(); }
        private void CancelExecute(object sender, ExecutedRoutedEventArgs e) { Close(); }
    }

那么xaml就是:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:w="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" WindowStartupLocation="CenterScreen" Closing="Window_Closing">
    <Window.CommandBindings>
        <CommandBinding Command="Save" Executed="SaveExecute" />
        <CommandBinding Command="New" Executed="NewExecute" />
        <CommandBinding Command="Close" Executed="CancelExecute" />
    </Window.CommandBindings>
    <Grid Margin="0,10,0,0">
        <DataGrid ItemsSource="{Binding DataList, Mode=OneTime}" ColumnWidth="*" Margin="10,0,9,38" HorizontalAlignment="Stretch"
                  AutoGenerateColumns="False" GridLinesVisibility="Horizontal"
                  HeadersVisibility="Column" HorizontalGridLinesBrush="LightGray" CanUserReorderColumns="False" Background="White"
                  PreparingCellForEdit="DataGrid_PreparingCellForEdit">
            <DataGrid.Resources>
                <DataTemplate x:Key="PasswordTemplate">
                    <PasswordBox w:PasswordHelper.Attach="True" w:PasswordHelper.Password="{Binding Password, Mode=TwoWay}" 
                                 BorderThickness="0" Height="23" HorizontalAlignment="Stretch" Width="130" />
                </DataTemplate>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name"  Binding="{Binding FirstName}"/>
                <DataGridTextColumn Header="Last Name"  Binding="{Binding LastName}"/>
                <DataGridTemplateColumn Header="Password" CellTemplate="{StaticResource PasswordTemplate}"
                                        CellEditingTemplate="{StaticResource PasswordTemplate}" />
            </DataGrid.Columns>
        </DataGrid>
        <Button
            Content="_New" Command="New"
            Width="75" Height="23" Margin="10,10,10,10"
            HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
        <Button
            Content="_Save" Command="Save"
            IsDefault="True"
            IsEnabled="True"
            Width="75" Height="23" Margin="10,10,91,10"
            HorizontalAlignment="Right" VerticalAlignment="Bottom" />
        <Button
            Content="Cancel" Command="Close"
            IsEnabled="True"
            Width="75" Height="23" Margin="10,10,10,10"
            HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
    </Grid>
</Window>

然后将http://wpftutorial.net/PasswordBox.html的PasswordHelper类添加到您的命名空间,瞧.

标签:c,wpf,passwordbox
来源: https://codeday.me/bug/20190628/1320334.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有