I have a case where I want to minimize the horizontal padding of a textbox.
Using snoop I found that the textbox consists of a multiple sub-controls. One of them is a TextBoxView with a margin of 2,0,2,0
The TextBoxView is an internal wpf component and has no public API.
How would you approach getting rid of the "internal padding"??
The Margin property of UIElement, which is parent class of all WPF controls is used to set the margin of a control. Margin property takes four numbers - Left, Top, Right and Bottom, that is margin to the left top and right bottom.
XAML Values Margin="20,50" will be interpreted to mean a Thickness with Left and Right set to 20, and Top and Bottom set to 50. The default unit for a Thickness measure is device-independent unit (1/96th inch). You can also specify other units by appending the unit type strings cm , in , or pt to any measure.
Padding represents the distance between the side of the control (which can be the margin) and its content. The content depends on the type of the control. Margin is outside the UI element, while Padding is inside it.
The Padding property represents the distance between an element and its child elements, and is used to separate the control from its own content. Padding values can be specified on layout classes.
Set the outer margin to -2,0,-2,0 to compensate for the padding.
I created a custom control that removes that internal padding.
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);
}
}
}
Here is a dirty way of doing it:
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;
}
}
}
}
It allows setting the margin on textboxes:
<Style TargetType="{x:Type TextBox}">
<Setter Property="demo:TextBoxView.Margin" Value="1,0" />
</Style>
Not optimized for performance at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With