问题描述
有人可以向我解释为什么PasswordBox控件不可滚动。
如您所见,当鼠标光标移到PasswordBox上时,滚动不起作用。我添加了默认和自定义的PasswordBox,两者的行为相同。
这是我创建的一个示例项目,用于更好的演示。
<Window
x:Class="PasswordBoxDemo.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"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="600"
WindowStartupLocation="CenterScreen">
<Window.Resources>
<Style targettype="{x:Type TextBox}">
<Setter Property="Padding" Value="12,8"/>
<Setter Property="Text" Value="Sample text"/>
</Style>
<Style targettype="{x:Type PasswordBox}">
<Setter Property="Padding" Value="12,8"/>
</Style>
</Window.Resources>
<ScrollViewer>
<StackPanel Margin="10" Height="800">
<TextBlock Margin="16" FontSize="32" textwrapping="Wrap">
Put your mouse on password Box area and try to scroll by mouse wheel.
</TextBlock>
<Label>Text:</Label>
<TextBox />
<Label>Password:</Label>
<PasswordBox Password="123456"/>
<Label>Text:</Label>
<TextBox />
<Label>Text:</Label>
<TextBox />
<Label>Password:</Label>
<PasswordBox Password="123456"/>
<Label>Text:</Label>
<TextBox />
<Label>Text:</Label>
<TextBox />
</StackPanel>
</ScrollViewer>
</Window>
解决方法
这似乎在内部抑制了密码框中的滚动鼠标事件。您可以执行将IsHitTestVisible
设置为false的操作,但这也会阻止其他鼠标事件的发生。
如果您不需要任何多余的装饰,请为PreviewMouseWheel
事件添加处理程序,如下所示:
<PasswordBox PreviewMouseWheel="PasswordBox_PreviewMouseWheel" />
为您的父级ScrollViewer命名:
<ScrollViewer Name="scrollViewer1">
然后在代码中实现处理程序回调,如下所示:
private void PasswordBox_PreviewMouseWheel(object sender,MouseWheelEventArgs e)
{
if (e.Delta != 0)
{
scrollViewer1.ScrollToVerticalOffset(scrollViewer1.VerticalOffset - e.Delta);
}
e.Handled = true;
}
这很丑陋,但是可行。
,我提出了另一种方法来向PasswordBox控件添加滚动行为。我认为这样比较干净。
public class PasswordBoxAssist
{
public static ScrollViewer GetParentScrollViewer(DependencyObject obj)
=> (ScrollViewer)obj.GetValue(ParentScrollViewerProperty);
public static void SetParentScrollViewer(DependencyObject obj,ScrollViewer value)
=> obj.SetValue(ParentScrollViewerProperty,value);
public static readonly DependencyProperty ParentScrollViewerProperty =
DependencyProperty.RegisterAttached("ParentScrollViewer",typeof(ScrollViewer),typeof(PasswordBoxAssist),new UIPropertyMetadata(default,OnParentScrollViewerChanged));
private static void OnParentScrollViewerChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
var passwordBox = (PasswordBox)d;
var scrollViewer = (ScrollViewer)e.NewValue;
if (scrollViewer is null)
passwordBox.PreviewMouseWheel -= OnPasswordBoxPreviewMouseWheel;
else
passwordBox.PreviewMouseWheel += OnPasswordBoxPreviewMouseWheel;
}
private static void OnPasswordBoxPreviewMouseWheel(object sender,MouseWheelEventArgs e)
{
var passwordBox = (PasswordBox)sender;
var scrollViewer = GetParentScrollViewer(passwordBox);
if (e.Delta != 0)
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
e.Handled = true;
}
}
<ScrollViewer x:Name="SampleScrollViewer">
<PasswordBox
[...]
local:PasswordBoxAssist.ParentScrollViewer="{Binding ElementName=SampleScrollViewer}"
[...]/>
</ScrollViewer>