C# 为什么WPF密码框有时变为空白,而其他密码框则变为空白?
我包括了一个示例程序:似乎在切换到密码框时,输入文本并进行切换会导致密码框变为空白。但是双击密码框,输入文本并跳出并不能。为什么会发生这种情况 编辑:我发现文本框也会出现这种情况,所以它不是PasswordBox特有的错误 重新创建每个场景的步骤: 使密码消失C# 为什么WPF密码框有时变为空白,而其他密码框则变为空白?,c#,wpf,passwordbox,C#,Wpf,Passwordbox,我包括了一个示例程序:似乎在切换到密码框时,输入文本并进行切换会导致密码框变为空白。但是双击密码框,输入文本并跳出并不能。为什么会发生这种情况 编辑:我发现文本框也会出现这种情况,所以它不是PasswordBox特有的错误 重新创建每个场景的步骤: 使密码消失 单击新建 单击“名字”字段 打字 按TAB键 打字 按TAB键 按TAB键(yes两次,否则将触发Save事件) 打字 注意点而不是文本-PasswordBox正在工作 按TAB键 当密码箱变为空白时,让您的朋友感到惊讶 使密码不消失
- 单击新建
- 单击“名字”字段
- 打字
- 按TAB键
- 打字
- 按TAB键
- 按TAB键(yes两次,否则将触发Save事件)
- 打字
- 注意点而不是文本-PasswordBox正在工作李>
- 按TAB键
- 当密码箱变为空白时,让您的朋友感到惊讶李>
- 单击新建
- 单击“名字”字段
- 打字
- 按TAB键
- 打字
- 双击密码字段
- 打字
- 注意点而不是文本-PasswordBox正在工作李>
- 按TAB键
- 让你的朋友感到惊奇的是。。等等,密码箱不是空的?WTF
使用系统;
使用System.Collections.ObjectModel;
命名空间WpfApplication1{
公共密封类MyData{
私有可观察收集数据列表;
公共ObservableCollection数据列表{get{return DataList;}}
public MyData(){dataList=newobserveCollection();}
public void AddBlankRow(){DataList.Add(new MyDataRow(this));}
}
公共密封类MyDataRow{
私有只读MyData MyData;
公共MyDataRow(MyData MyData){this.MyData=MyData;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串密码{get;set;}
}
}
使用制度;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Input;
命名空间WpfApplication1{
公共部分类主窗口:窗口{
私有MyData数据{get{return(MyData)DataContext;}}
公共主窗口(){InitializeComponent();}
私有无效密码箱\u密码已更改(对象发送方,RoutedEventArgs e){
密码箱pb=(密码箱)发送方;
如果(pb!=null){
MyDataRow row=pb.DataContext作为MyDataRow;
如果(row!=null){row.Password=pb.Password;}
}
}
私有无效窗口_已加载(对象发送方,RoutedEventArgs e){DataContext=new MyData();}
私有无效窗口\正在关闭(对象发送方,System.ComponentModel.CancelEventArgs e){}
私有void SaveExecute(对象发送方,ExecutedRoutedEventArgs e){}
私有void NewExecute(对象发送方,ExecutedRoutedEventArgs e){Data.AddBlankRow();}
私有void CancelExecute(对象发送方,ExecutedRoutedEventArgs e){Close();}
}
}
编辑
使用CellTemplate和EditingCellTemplate的数据模板,
我的工作只是保持一致——总是展示一些东西(在本例中是一个省略)。这样,不管怎样,当密码箱失去焦点时,它会变回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
)。通常的解决方法是使用绑定,并使两个单独的模板都绑定到同一数据段,如下所示:
但是,出于安全原因,PasswordBox
当然不允许您绑定到Password
(因为Password
不是依赖属性)。如果这不是一个很大的问题(我不完全理解为什么会这样,但我想他们不希望明文密码在绑定中四处飞来飞去,而没有人知道他们在做什么),那么您可以按照本文的下半部分创建绑定:-使用自定义静态依赖属性
因此,我在下面的代码中实现了这一过程,并且通过向PreparingCellForEdit
事件添加一个处理程序,修复了密码框没有正确聚焦并且需要两个选项卡的错误,如
总之,我的工作示例的示例代码是:
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(); }
}
使用系统;
使用System.Collections.ObjectModel;
命名空间WpfApplication1{
公共密封类MyData{
私有可观察收集数据列表;
公共ObservableCollection数据列表{get{return DataList;}}
public MyData(){dataList=newobserveCollection();}
public void AddBlankRow(){DataList.Add(new MyDataRow(this));}
}
公共密封类MyDataRow{
私有只读MyData MyData;
公共MyDataRow(MyData MyData){this.MyData=MyData;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串密码{get;set;}
}
}
使用制度;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Input;
使用System.Windows.Media;
命名空间WpfApplication1{
公共部分类主窗口:窗口
{
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(); }
}
<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>