我使用的是密码框,每次从 UI 更改密码时都需要执行一些操作。此密码框是 WPF 窗口中页面的一部分,当页面更改/卸载时,passwordchanged 事件似乎会被触发,密码值为空。我们有什么方法可以识别这个事件的来源是页面卸载而不是用户在 UI 中更改密码吗?
编辑 - 添加示例代码以重现案例。有一个 MainWindow,其中包含一个用于呈现页面的 Frame 元素。有 2 个示例页面 Page1.xaml 和 Page2.xaml。 Page1 有一个密码框和文本框,当其值更改时,主窗口中的文本也会更改并显示新值。当页面更改时,也会使用“”值触发密码更改事件,但不会触发 textchanged 事件。我可以防止 pwdChanged 事件在这里被触发吗?
<Window x:Class="WpfPasswwordTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfPasswwordTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Name="PasswordTextLabel" HorizontalContentAlignment="Center"></Label>
<Label Grid.Row="1" Name="TextboxLabel" HorizontalContentAlignment="Center"></Label>
<Button Grid.Row="2" Name="PageChangeButton" Height="50" Width="200" Content="Change page"/>
<Frame Name="PageFrame" Grid.Row="3" NavigationUIVisibility="Hidden">
</Frame>
</Grid>
public partial class MainWindow : Window
{
public Label pwdLabel, txtboxLabel;
private bool page1 = true;
public MainWindow()
{
InitializeComponent();
pwdLabel = PasswordTextLabel;
txtboxLabel = TextboxLabel;
Class1.Instance.mainWin = this;
PasswordTextLabel.Content = "Pwd not changed yet";
TextboxLabel.Content = "Textbox text not changed yet";
PageFrame.Source = new Uri("Page1.xaml", UriKind.Relative);
PageChangeButton.Click += pageChange;
}
private void pageChange(object s, EventArgs e)
{
if(page1)
PageFrame.Source = new Uri("Page2.xaml", UriKind.Relative);
else
PageFrame.Source = new Uri("Page1.xaml", UriKind.Relative);
page1 = !page1;
}
}
<Page x:Class="WpfPasswwordTest.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfPasswwordTest"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Page1">
<Grid Height="auto" Width="500">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0"> This is page 1</Label>
<Label Name="SampleLabel" Grid.Row="1">Password box - </Label>
<PasswordBox Name="SamplePwdBox" Grid.Row="2"></PasswordBox>
<Label Name="SampleTextLabel" Grid.Row="3">Text box -</Label>
<TextBox Name="SampleTxtBox" Grid.Row="4"></TextBox>
</Grid>
public partial class Page1 : Page
{
public Page1()
{
InitializeComponent();
SamplePwdBox.PasswordChanged += pwdChanged;
SampleTxtBox.TextChanged += txtChanged;
}
private void pwdChanged(object s,EventArgs e)
{
Class1.Instance.mainWin.pwdLabel.Content = "pwd Changed to " + (s as PasswordBox)?.Password;
}
private void txtChanged(object s, EventArgs e)
{
Class1.Instance.mainWin.txtboxLabel.Content = "text Changed to " + (s as TextBox)?.Text;
}
}
<Page x:Class="WpfPasswwordTest.Page2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfPasswwordTest"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Page2">
<Grid Height="100" Width="500">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0">This is page 2</Label>
<Label Name="SampleLabel" Grid.Row="1">Nothing to show here</Label>
</Grid>
您的问题是关于检查PasswordChanged事件的来源,目的是找出您的代码可能存在的问题。这个答案提供了一些调试策略来回答这个问题,而不是尝试解决您的代码遇到的根本问题。
将
object
传入处理程序作为发送者,并尝试使用 if(s is Control ctrl)...
从中获取可用类型
输出一些信息到 Debug 窗口以帮助查看发生了什么:
Debug.WriteLine($"Sender is {ctrl.Name} Prev: {_prevPswd} Current {SamplePwdBox.Password}");
添加
_prevPswd
变量以帮助了解事件触发的原因。当输入“abc”作为密码时,这些字符会被记录,但当页面更改时,密码框会被清除。
捕捉它被清除的那一刻。
if (string.IsNullOrWhiteSpace(SamplePwdBox.Password)){}
并使用 Call Stack 窗口尝试查看是什么调用者导致事件发生。
因此,这是在事件处理程序中及其周围添加的调试代码:
string _prevPswd = string.Empty;
private void pwdChanged(object s, EventArgs e)
{
if(s is Control ctrl)
{
Debug.WriteLine($"Sender is {ctrl.Name} Prev: {_prevPswd} Current {SamplePwdBox.Password}");
_prevPswd = SamplePwdBox.Password;
if (string.IsNullOrWhiteSpace(SamplePwdBox.Password))
{ }
}
Class1.Instance.mainWin.pwdLabel.Content = "pwd Changed to " + (s as PasswordBox)?.Password;
}
现在设置断点:
并检查 Call Stack 窗口以查看代码来自何处。
问题似乎是,随着现在的编码,
Page1
是一个短暂的对象,一旦不再显示就会被丢弃。该事件正在触发,因为发生这种情况时文本将变为空。现在您知道发生了什么,您可以开始评估您遇到的问题的解决方案。希望这为您提供了一些新工具来“检查事件的来源”。