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

C# 使WPF文本框边距可单击/可选择,c#,wpf,textbox,C#,Wpf,Textbox,我有一个白色背景的WPF文本框。我给了它一些填充,以便文本周围有一个“边距”(类似于MS Word中的边距) 但是,与Word不同的是,文本周围的空白区域不是“活动的”(请参见下面的彩色编码插图)。在文本框内单击(红色部分)不会移动文本框的插入符号,也不会开始选择。但是请注意,整个绿色区域是活跃的-甚至是文本下面的空白空间(意思是你可以点击它来移动插入符号或者开始选择)……/P> P> >,我的问题是:有没有办法在“代码>文本框< /代码>周围添加空格,它是空白的,但也是可编辑区域的一部

我有一个白色背景的WPF
文本框
。我给了它一些
填充
,以便文本周围有一个“边距”(类似于MS Word中的边距)


但是,与Word不同的是,文本周围的空白区域不是“活动的”(请参见下面的彩色编码插图)。在文本框内单击(红色部分)不会移动文本框的插入符号,也不会开始选择。但是请注意,整个绿色区域是活跃的-甚至是文本下面的空白空间(意思是你可以点击它来移动插入符号或者开始选择)……/P>

<> P> >,我的问题是:有没有办法在“代码>文本框< /代码>周围添加空格,它是空白的,但也是可编辑区域的一部分(这样它会对点击/选择做出反应,比如绿色部分的空白区域)?

谢谢


p、 在我寻找答案的过程中,最接近美国的是:。。。但是,虽然增加内部
TextBoxView
Margin
确实增加了文本周围的空间,但该空间似乎仍然没有以任何方式处于“活动”状态。。。而且
TextBoxView
似乎没有
Padding
属性,所以我不能尝试(尽管我认为
Padding
Margin
更可能是解决方案)…

我真的很困惑为什么它不是一个流行的问题。文本框肯定有违反直觉的填充行为

查看了Microsoft ReferenceSource中的文本框选择代码,但结果太复杂,无法插入修复程序。所以行为附加属性似乎是实现这一点的最简单方法

xaml:


c#:

公共静态类TextBoxSelectionBehavior
{
公共常数双倍最大距离=10;
私有静态文本框控件;
专用静态点pos机;
私有静态int启动;
私有静态int-cur;
私人静态双重权利;
私有静态布尔阻力;
private const double maxrag=12;
public static readonly dependencProperty IsEnabledProperty=dependencProperty.RegisterAttached(“IsEnabled”,typeof(bool),typeof(TextBoxSelectionBehavior),new UIPropertyMetadata(false,IsEnabledChanged));
公共静态bool GetIsEnabled(FrameworkElement obj)=>(bool)obj.GetValue(IsEnabledProperty);
public static void SetIsEnabled(FrameworkElement obj,bool value)=>obj.SetValue(IsEnabledProperty,value);
私有静态void IsEnabledChanged(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
var v=(文本框)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;
}
其他的
{
v、 PreviewMouseDown-=v_PreviewMouseDown;
v、 PreviewMouseUp-=v_PreviewMouseUp;
v、 PreviewMouseMove-=v_PreviewMouseMove;
v、 LostFocus-=v_LostFocus;
v、 IsKeyboardFocusedChanged-=v_IsKeyboardFocusedChanged;
}
}
公共静态只读DependencyProperty ClickSelectsProperty=DependencyProperty.RegisterAttached(“ClickSelects”、typeof(bool)、typeof(TextBoxSelectionBehavior)、new UIPropertyMetadata(true));
公共静态bool GetClickSelects(FrameworkElement obj)=>(bool)obj.GetValue(clickselects属性);
公共静态无效设置单击选择(FrameworkElement obj,布尔值)=>obj.SetValue(单击选择属性,值);
私有静态void V_PreviewMouseDown(对象发送器,System.Windows.Input.MouseButtonEventArgs e)
{
如果(e.ChangedButton!=MouseButton.Left)返回;
if(control!=null){control.ReleaseMouseCapture();control=null;}
如果(例如,OriginalSource是网格g&&(System.Windows.Media.VisualTreeHelper.GetParent(g)作为FrameworkElement)?.Name==“PART\U ContentHost”)
{
控件=(文本框)发送方;
pos=e.GetPosition(控制);
var r=control.FindChild().Content作为FrameworkElement;
右=r.TranslatePoint(新点(r.ActualWidth,0),控件).X;
cur=start=control.GetCharacterIndexFromPoint(pos,true)+(pos.X>=right?1:0);
control.SelectionStart=开始;
control.SelectionLength=0;
control.Focus();
control.CaptureMouse();
阻力=假;
e、 已处理=正确;
}
}
私有静态void V_PreviewMouseMove(对象发送器,System.Windows.Input.MouseEventArgs e)
{
if(control==null)返回;
var p=e.GetPosition(控制);
cur=control.GetCharacterIndexFromPoint(p,true);
control.SelectionStart=Math.Min(开始,当前);
control.SelectionLength=Math.Abs(cur-start)+(p.X>=右侧?位置X>=右侧?-1:0);
如果(!drag)drag=Math.Max(Math.Abs(pos.X-p.X),Math.Abs(pos.Y-p.Y))>MAXDRAG;
e、 已处理=正确;
}
私有静态void V_PreviewMouseUp(对象发送器,System.Windows.Input.MouseButtonEventArgs e)
{
if(control==null)返回;
控件。释放mouseCapture();
如果(!drag&&GetClickSelects(control))控件。SelectAll();
e、 已处理=正确;
控制=空;
}
私有静态void V_LostFocus(对象发送方,路由目标)
{
if(control!=null&&control!=sender)返回;
if(control!=null)control.ReleaseMouseCapture();
控制=空;
}
私有静态void V_IsKeyboardFocusedChanged(对象发送方,DependencyPropertyChangedEventArgs e)
{
if(control!=null&&control!=sender)返回;
如果((bool)e.NewValue)返回;
if(control!=null)control.ReleaseMouseCapture();
控制=空;
}
}
这是所附的财产c
<TextBox Padding="24 0" local:TextBoxSelectionBehavior.IsEnabled="True"/>
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;
    }
}