gpt4 book ai didi

c# - 使 WPF 文本框边距可单击/可选择

转载 作者:行者123 更新时间:2023-12-03 17:37:47 27 4
gpt4 key购买 nike

我有一个 WPF TextBox白色背景。我给了它一些 Padding这样文本周围就有一个“边距”(类似于 MS Word 中的边距)。

<TextBox x:Name="MyTextBox" Padding="25" />

然而,与 Word 不同的是,文本周围的这个空白区域不是“事件的”(参见下面的颜色编码插图)。在其中单击(红色部分)不会移动文本框的插入符号,也不会开始选择。但是请注意,整个绿色区域都处于事件状态 - 甚至是文本下方的空白区域(这意味着您可以在其中单击以移动插入符号或开始选择)...

textbox with colored alive/dead zones

所以,我的问题是:有没有办法在 TextBox 周围添加空间?那是空白的,但也是可编辑区域的一部分(这样它就会对点击/选择使用react,就像绿色部分的空白区域一样)?

谢谢!

p.s.我在寻找答案时最接近的是: How to set the margin on a internal TextBoxView in wpf ... 但是,在增加 Margin 的同时内部 TextBoxView确实增加了文本周围的空间,该空间似乎仍然没有以任何方式“活跃”...而且看起来像 TextBoxView没有 Padding属性(property),所以我不能尝试(尽管我想 PaddingMargin 更有可能是解决方案)...

最佳答案

我真的很困惑为什么这不是一个受欢迎的问题。 TextBox 肯定具有违反直觉的填充行为。
查看 Microsoft 引用源以获取 TextBox 选择代码,但事实证明它太复杂而无法注入(inject)修复程序。所以 Behavior 附加属性似乎是实现这一目标的最简单方法。
xml:

<TextBox Padding="24 0" local:TextBoxSelectionBehavior.IsEnabled="True"/>
C#:
public static class TextBoxSelectionBehavior
{
public const double MAX_DISTANCE = 10;
private static TextBox control;
private static Point pos;
private static int start;
private static int cur;
private static double right;
private static bool drag;
private const double MAXDRAG = 12;

public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(TextBoxSelectionBehavior), new UIPropertyMetadata(false, IsEnabledChanged));
public static bool GetIsEnabled(FrameworkElement obj) => (bool)obj.GetValue(IsEnabledProperty);
public static void SetIsEnabled(FrameworkElement obj, bool value) => obj.SetValue(IsEnabledProperty, value);
private static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var v = (TextBox)d;
if ((bool)e.NewValue)
{
v.PreviewMouseDown += V_PreviewMouseDown;
v.PreviewMouseUp += V_PreviewMouseUp;
v.PreviewMouseMove += V_PreviewMouseMove;
v.LostFocus += V_LostFocus;
v.IsKeyboardFocusedChanged += V_IsKeyboardFocusedChanged;
}
else
{
v.PreviewMouseDown -= V_PreviewMouseDown;
v.PreviewMouseUp -= V_PreviewMouseUp;
v.PreviewMouseMove -= V_PreviewMouseMove;
v.LostFocus -= V_LostFocus;
v.IsKeyboardFocusedChanged -= V_IsKeyboardFocusedChanged;
}
}

public static readonly DependencyProperty ClickSelectsProperty = DependencyProperty.RegisterAttached("ClickSelects", typeof(bool), typeof(TextBoxSelectionBehavior), new UIPropertyMetadata(true));
public static bool GetClickSelects(FrameworkElement obj) => (bool)obj.GetValue(ClickSelectsProperty);
public static void SetClickSelects(FrameworkElement obj, bool value) => obj.SetValue(ClickSelectsProperty, value);

private static void V_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (e.ChangedButton != MouseButton.Left) return;
if (control != null) { control.ReleaseMouseCapture(); control = null; }
if (e.OriginalSource is Grid g && (System.Windows.Media.VisualTreeHelper.GetParent(g) as FrameworkElement)?.Name == "PART_ContentHost")
{
control = (TextBox)sender;
pos = e.GetPosition(control);
var r = control.FindChild<ScrollContentPresenter>().Content as FrameworkElement;
right = r.TranslatePoint(new Point(r.ActualWidth, 0), control).X;
cur = start = control.GetCharacterIndexFromPoint(pos, true) + (pos.X >= right ? 1 : 0);
control.SelectionStart = start;
control.SelectionLength = 0;
control.Focus();
control.CaptureMouse();
drag = false;
e.Handled = true;
}
}
private static void V_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (control == null) return;
var p = e.GetPosition(control);
cur = control.GetCharacterIndexFromPoint(p, true);
control.SelectionStart = Math.Min(start, cur);
control.SelectionLength = Math.Abs(cur - start) + (p.X >= right ? pos.X >= right ? -1 : 1 : 0);
if (!drag) drag = Math.Max(Math.Abs(pos.X - p.X), Math.Abs(pos.Y - p.Y)) > MAXDRAG;
e.Handled = true;
}
private static void V_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (control == null) return;
control.ReleaseMouseCapture();
if (!drag && GetClickSelects(control)) control.SelectAll();
e.Handled = true;
control = null;
}
private static void V_LostFocus(object sender, RoutedEventArgs e)
{
if (control != null && control != sender) return;
if (control != null) control.ReleaseMouseCapture();
control = null;
}
private static void V_IsKeyboardFocusedChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (control != null && control != sender) return;
if ((bool)e.NewValue) return;
if (control != null) control.ReleaseMouseCapture();
control = null;
}
}
并且这个附加属性可以很容易地被一个通用的样式 setter 全局分配给一个文本框。

关于c# - 使 WPF 文本框边距可单击/可选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44231590/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com