如何检查WPF PasswordBox中PasswordChanged事件的来源?

问题描述 投票:0回答:1

我使用的是密码框,每次从 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>
c# .net wpf wpf-controls
1个回答
0
投票

您的问题是关于检查PasswordChanged事件的来源,目的是找出您的代码可能存在的问题。这个答案提供了一些调试策略来回答这个问题,而不是尝试解决您的代码遇到的根本问题。

  1. object
    传入处理程序作为发送者,并尝试使用
    if(s is Control ctrl)...

    从中获取可用类型
  2. 输出一些信息到 Debug 窗口以帮助查看发生了什么:

    Debug.WriteLine($"Sender is {ctrl.Name} Prev: {_prevPswd} Current {SamplePwdBox.Password}");

  3. 添加

    _prevPswd
    变量以帮助了解事件触发的原因。当输入“abc”作为密码时,这些字符会被记录,但当页面更改时,密码框会被清除。

  4. 捕捉它被清除的那一刻。

    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
是一个短暂的对象,一旦不再显示就会被丢弃。该事件正在触发,因为发生这种情况时文本将变为空。现在您知道发生了什么,您可以开始评估您遇到的问题的解决方案。希望这为您提供了一些新工具来“检查事件的来源”。

© www.soinside.com 2019 - 2024. All rights reserved.