如何在 wpf 中的内部 TextBoxView 上设置边距

Posted

技术标签:

【中文标题】如何在 wpf 中的内部 TextBoxView 上设置边距【英文标题】:How to set the margin on a internal TextBoxView in wpf 【发布时间】:2022-03-08 14:22:55 【问题描述】:

我有一个案例,我想最小化文本框的水平填充。

使用 snoop 我发现文本框由多个子控件组成。 其中之一是边距为 2,0,2,0 的 TextBoxView

TextBoxView 是一个内部 wpf 组件,没有公共 API。

您将如何摆脱“内部填充”??

【问题讨论】:

【参考方案1】:

将外边距设置为 -2,0,-2,0 以补偿填充。

【讨论】:

TextBoxView 在问题中应用了 Margin(不是填充)错误文本,我会更新它。将父控件的边距设置为 -2 似乎没有帮助。 好主意。对我有用,但无论如何我都禁用了边框,还需要将背景设置为x:Null,这在我的情况下是可以的。【参考方案2】:

我创建了一个自定义控件来删除该内部填充。

public class MyTextBox : TextBox

    public MyTextBox()
    
        Loaded += OnLoaded;
                     

    void OnLoaded(object sender, RoutedEventArgs e)
    
        // the internal TextBoxView has a margin of 2,0,2,0 that needs to be removed
        var contentHost = Template.FindName("PART_ContentHost", this) as ScrollViewer;
        if (contentHost != null && contentHost.Content != null && contentHost.Content is FrameworkElement)
        
            var textBoxView = contentHost.Content as FrameworkElement;
            textBoxView.Margin = new Thickness(0,0,0,0);
        
           

【讨论】:

【参考方案3】:

这是一种肮脏的做法:

public static class TextBoxView

    public static readonly DependencyProperty MarginProperty = DependencyProperty.RegisterAttached(
        "Margin",
        typeof(Thickness?),
        typeof(TextBoxView),
        new PropertyMetadata(null, OnTextBoxViewMarginChanged));

    public static void SetMargin(TextBox element, Thickness? value)
    
        element.SetValue(MarginProperty, value);
    

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static Thickness? GetMargin(TextBox element)
    
        return (Thickness?)element.GetValue(MarginProperty);
    

    private static void OnTextBoxViewMarginChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    
        var textBox = (TextBox)d;
        OnTextBoxViewMarginChanged(textBox, (Thickness?)e.NewValue);
    

    private static void OnTextBoxViewMarginChanged(TextBox textBox, Thickness? margin)
    
        if (!textBox.IsLoaded)
        
            textBox.Dispatcher.BeginInvoke(
                DispatcherPriority.Loaded,
                new Action(() => OnTextBoxViewMarginChanged(textBox, margin)));
            return;
        

        var textBoxView = textBox.NestedChildren()
                                 .SingleOrDefault(x => x.GetType().Name == "TextBoxView");
        if (margin == null)
        
            textBoxView?.ClearValue(FrameworkElement.MarginProperty);
        
        else
        
            textBoxView?.SetValue(FrameworkElement.MarginProperty, margin);
        
    

    private static IEnumerable<DependencyObject> NestedChildren(this DependencyObject parent)
    
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
        
            var child = VisualTreeHelper.GetChild(parent, i);
            yield return child;
            if (VisualTreeHelper.GetChildrenCount(child) == 0)
            
                continue;
            

            foreach (var nestedChild in NestedChildren(child))
            
                yield return nestedChild;
            
        
    

它允许设置文本框的边距:

<Style TargetType="x:Type TextBox">
    <Setter Property="demo:TextBoxView.Margin" Value="1,0" />
</Style>

根本没有针对性能进行优化。

【讨论】:

以上是关于如何在 wpf 中的内部 TextBoxView 上设置边距的主要内容,如果未能解决你的问题,请参考以下文章

如何从WPF中的代码修改setter

浅谈WPF中的PreviewTextInput

WPF GetIsInDesignMode 从转换器内部

浅谈WPF中的PreviewTextInput

C# wpf 如何实现自定义控件,布局时,大小发生变化,内部绘制的曲线跟随变化?

将内部datagrid数据与外部datagrid wpf绑定