Задать CornerRadius как Attached Property для ComboBox

197
28 июля 2018, 19:20

Я смог сделать CornerRadius как Attached property для Button и TextBox с помощью класса

public class CornerRadiusSetter
{
    public static CornerRadius GetCornerRadius(DependencyObject obj) => (CornerRadius)obj.GetValue(CornerRadiusProperty);
    public static void SetCornerRadius(DependencyObject obj, CornerRadius value) => obj.SetValue(CornerRadiusProperty, value);
    public static readonly DependencyProperty CornerRadiusProperty =
        DependencyProperty.RegisterAttached(nameof(Border.CornerRadius), typeof(CornerRadius),
            typeof(CornerRadiusSetter), new UIPropertyMetadata(new CornerRadius(), CornerRadiusChangedCallback));
    public static void CornerRadiusChangedCallback(object sender, DependencyPropertyChangedEventArgs e)
    {
        Control control = sender as Control;
        if (control == null) return;
        control.Loaded += Control_Loaded;
    }
    private static void Control_Loaded(object sender, EventArgs e)
    {
        Control control = sender as Control;
        if (control == null || control.Template == null) return;
        control.ApplyTemplate();
        Border border = control.Template.FindName("border", control) as Border;
        if (border == null) return;
        border.CornerRadius = GetCornerRadius(control);
    }
}

Это позволяет задать произвольный CornerRadius в XAML:

<TextBox local:CornerRadiusSetter.CornerRadius="5" />
<Button local:CornerRadiusSetter.CornerRadius="15">Button</Button>

Как сделать чтобы этот класс срабатывал ещё и для ComboBox?

После control.ApplyTemplate() добавлял такой код

Control toggleButton = control.Template.FindName("toggleButton", control) as Control;
if (toggleButton != null)
    SetCornerRadius(toggleButton, GetCornerRadius(control));
Border dropDownBorder = control.Template.FindName("DropDownBorder", control) as Border;
if (dropDownBorder != null)
    dropDownBorder.CornerRadius = GetCornerRadius(control);

Но ничего не менялось.

Answer 1

У меня на Windows 10 для ComboBox сработало следующее:

var toggleButton = control.Template.FindName("toggleButton", control) as ToggleButton;
var border = toggleButton.Template.FindName("templateRoot", toggleButton) as Border;
border.CornerRadius = GetCornerRadius(control);

т.е. вы просто ошиблись с именем элемента в шаблоне (запутались в стилях?)

Answer 2

Для ComboBox надо немноого добавить существующий метод обработки загрузки и добавить различные улучшения для стилей самого выпадающего списка, чтобы у него не было торчащих углов.

public static class CornerRadiusSetter
{
    public static CornerRadius GetCornerRadius(DependencyObject obj) => (CornerRadius)obj.GetValue(CornerRadiusProperty);
    public static void SetCornerRadius(DependencyObject obj, CornerRadius value) => obj.SetValue(CornerRadiusProperty, value);
    public static readonly DependencyProperty CornerRadiusProperty =
        DependencyProperty.RegisterAttached(nameof(Border.CornerRadius), typeof(CornerRadius),
            typeof(CornerRadiusSetter), new UIPropertyMetadata(new CornerRadius(), CornerRadiusChangedCallback));
    public static void CornerRadiusChangedCallback(object sender, DependencyPropertyChangedEventArgs e)
    {
        Control control = sender as Control;
        if (control == null) return;
        control.Loaded -= Control_Loaded;
        control.Loaded += Control_Loaded;
    }
    private static void Control_Loaded(object sender, EventArgs e)
    {
        Control control = sender as Control;
        if (control == null || control.Template == null) return;
        control.ApplyTemplate();
        CornerRadius cornerRadius = GetCornerRadius(control);
        if (control is ComboBox)
            StyleComboBox(control, cornerRadius);
        else
        {
            // setting borders for non-combobox controls
            Border border = control.Template.FindName("border", control) as Border;
            if (border == null) return;
            border.CornerRadius = cornerRadius;
        }
    }
    private static void StyleComboBox(Control control, CornerRadius cornerRadius)
    {
        Control toggleButton = control.Template.FindName("toggleButton", control) as Control;
        if (toggleButton == null) return;
        toggleButton.ApplyTemplate();
        // Set border radius for border radius border
        Border toggleButtonBorder = toggleButton.Template.FindName("templateRoot", toggleButton) as Border;
        toggleButtonBorder.CornerRadius = cornerRadius;
        // Decrease width of dropdown and center it to avoid showing "sticking" dropdown corners
        Popup popup = control.Template.FindName("PART_Popup", control) as Popup;
        if (popup != null)
            popup.HorizontalOffset = cornerRadius.BottomLeft;
        Decorator shadowChrome = control.Template.FindName("shadow", control) as Decorator;
        if (shadowChrome != null)
        {
            double minWidth = control.ActualWidth - cornerRadius.BottomLeft - cornerRadius.BottomRight;
            if (minWidth > 0)
            {
                shadowChrome.MinWidth = minWidth;
                shadowChrome.Width = minWidth;
            }
        }
    }
}
READ ALSO
Не отображается текст из файла в ListBox-e

Не отображается текст из файла в ListBox-e

После перезагрузки компьютера перестали выводиться данные из файла в ListBox, но при этом ошибок при компиляции не выявляются, просто при нажатии...

185
Wpf Calendar изменение CalendarItem

Wpf Calendar изменение CalendarItem

Вопрос такой возможно ли создание/изменение стиля CalendarItem так чтобы можно было отображать еще и доп значение(грубо говоря номер) из модели...

252
Как передать сумму в POS терминал?

Как передать сумму в POS терминал?

Пишу аналог кассового терминала для WindowsДля оплаты используются наличные или карта

202
Проблемы с Rabbitmq

Проблемы с Rabbitmq

Использую php-amqplib/rabbitmq-bundle Все работает нормально до момента пока Rabbit не обваливаетсяВопрос: как можно избежать этих ошибок

219