【问题标题】:PasswordBox Visual States are missing?缺少 PasswordBox 视觉状态?
【发布时间】:2023-03-25 17:32:01
【问题描述】:

我正在尝试设置PasswordBox 的可视状态,以在密码不正确时指示错误。

根据 MSDN 文档 PasswordBox Syles and Templates(他们的拼写错误),在以下视觉状态组中定义了以下视觉状态:

  • 正常 - CommonStates
  • MouseOver - CommonStates
  • 已禁用 - CommonStates
  • 专注 - FocusStates
  • 不专注 - FocusStates
  • 有效 - ValidationStates
  • InvalidFocused - ValidationStates
  • InvalidUnfocused - ValidationStates

然而,下面的代码总是返回一个空列表:

public void Blah(PasswordBox passwordBox)
{
     var visualStateGroups = VisualStateManager.GetVisualStateGroups(passwordBox);
     //visualStates.Count is always 0.
}

并且试图进入一个状态总是返回 false,例如

public void Halb(PasswordBox passwordBox)
{
   bool didTransition = VisualStateManager.GoToState(passwordBox, 
                                                    "InvalidFocused", 
                                                     true);

   //didTransition is always false. It doesn't make a difference whether
   //or not the last paramter is "true" or "false"
}

为什么在 msdn 上记录的 VisualStates/VisualStateGroups 显然在代码中丢失了?我做错了什么(我的怀疑),还是 MSDN 不正确?

【问题讨论】:

    标签: .net wpf c#-4.0


    【解决方案1】:

    你问题答案的第一部分在 MSDN VisualStateManager.GetVisualStateGroupscmets

    “VisualStateGroups 通常设置在元素可视化树的根部,而不是元素本身。”

    所以

    public void Blah(PasswordBox passwordBox)
    {
        var bd = pbox.Template.FindName("Bd", pbox) as FrameworkElement;
        var visualStateGroups = VisualStateManager.GetVisualStateGroups(bd);
        Debug.WriteLine(visualStateGroups.Count);
        // should print 3
    }
    

    至于第二部分,这对我来说很好,

    如果我定义 VSG,例如

    <VisualStateManager.VisualStateGroups>
      <VisualStateGroup x:Name="CommonStates" />
      <VisualStateGroup x:Name="FocusStates" />
      <VisualStateGroup x:Name="ValidationStates">
        <VisualState x:Name="Valid" />
        <VisualState x:Name="InvalidFocused">
          <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentHost"
                                          Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
              <EasingColorKeyFrame KeyTime="0"
                                    Value="#FF9B4A4A" />
            </ColorAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
        <VisualState x:Name="InvalidUnfocused" />
      </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    

    现在VisualStateManager.GoToState(passwordBox, "InvalidFocused", true); 返回true,我可以看到相应样式的控件。

    更新:

    AFAIK 认为只是在 Silverlight 中自动为 PasswordBox 定义了 VisualState。在 WPF 中,您必须自己定义它们。表达式混合通过在 IDE 的 States 选项卡中为您提供状态略有帮助,当您记录更改时,它会自动生成伴随 Storyboard 的代码,但如果您不编辑 Template就是这样。

    As stated here 猜测这只是因为 WPF 中的默认样式不使用开箱即用的 VSM。

    Download link 到一个示例,其中“我们”明确定义了 VSM 和 VisualStatePasswordBox,而我之前发布的两个函数最初都显示有效。

    【讨论】:

    • 感谢您的回复。您的第一个示例为bd 提供了null(我尝试用"passwordBox" 替换"Bd",因为我的xaml 是&lt;PasswordBox x:Name="passwordBox" ... 具有相同的结果。)至于第二个,我可能在这里遗漏了一些基本的东西,但不应该已经定义了 VisualStates 吗?为什么我必须在 Xaml 中重新定义它们?
    • 不确定是否相关,但passwordBox.Template.VisualTree 也是null,这不是我期望找到的。
    • @Nathan 我已经更新了我的答案,还包括一个示例下载,您可以尝试显示这些功能是否正常工作,但请务必在 WPF 中定义 VisualState,因为它们确实如此不像silverlight,默认情况下不使用VSM。
    • 您的示例有效,我现在看到"Bd" 是您在样式模板中定义的控件。但是,一个有趣的消息是,如果我将所有出现的 InvalidFocused 重命名为其他任何名称,您的示例仍然有效。因此,我们似乎是在完整地定义视觉状态——这让我想知道为什么msdn.microsoft.com/en-us/library/ff468216%28v=vs.100%29.aspx 甚至存在,因为记录的状态似乎没有任何影响,而且页面没有提到 Silverlight。无论如何,这让我能够继续前进。
    • @Nathan 确实没多大用处。可能只是作为控件通常具有的不同可能状态的提示。至于文档,我在答案中发布的链接有回复 Thanks for pointing out that the help topic does not make that clear ... Again, thanks for pointing out the doc issue. I also encourage you to send feedback about the docs for such issues. (There is a feedback link for each topic at the bottom of each page) 猜他们还没有解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-16
    • 1970-01-01
    • 1970-01-01
    • 2011-09-01
    • 1970-01-01
    相关资源
    最近更新 更多