Как изменить ТОЛЬКО правое (или левое, верхнее, нижнее) значение свойства Margin элемента управления WPF?

Это довольно легко сделать из кода:

var button = new Button();
var margin = button.Margin;
margin.Right = 10;
button.Margin = margin;

В XAML, однако, я ограничен следующим:

<Button Margin="0,0,10,0" />

Проблема в том, что теперь я потенциально перезаписываю другие значения полей (то есть слева, сверху, снизу), устанавливая их в ноль).

Есть ли способ получить XAML, как показано ниже?

<Button MarginRight="10" />

4 ответа

Решение

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

Например, определите следующий класс где-нибудь в вашем приложении:

using System;
using System.Windows;
using System.Windows.Controls;

namespace YourApp.AttachedProperties
{
    public class MoreProps
    {
        public static readonly DependencyProperty MarginRightProperty = DependencyProperty.RegisterAttached(
            "MarginRight",
            typeof(string),
            typeof(MoreProps),
            new UIPropertyMetadata(OnMarginRightPropertyChanged));

        public static string GetMarginRight(FrameworkElement element)
        {
            return (string)element.GetValue(MarginRightProperty);
        }

        public static void SetMarginRight(FrameworkElement element, string value)
        {
            element.SetValue(MarginRightProperty, value);
        }

        private static void OnMarginRightPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            var element = obj as FrameworkElement;

            if (element != null)
            {
                int value;
                if (Int32.TryParse((string)args.NewValue, out value))
                {
                    var margin = element.Margin;
                    margin.Right = value;
                    element.Margin = margin;
                }
            }
        }
    }
}

Теперь в вашем XAML все, что вам нужно сделать, это объявить следующее пространство имен:

xmlns:ap="clr-namespace:YourApp.AttachedProperties"

И тогда вы можете написать XAML, например:

<Button ap:MoreProps.MarginRight="10" />



Кроме того, вы можете избежать использования присоединенного свойства и вместо этого написать немного более длинный XAML, такой как:

<Button>
<Button.Margin>
<Thickness Right="10" />
</Button.Margin>
</Button>

Вы можете привязать данные Margin к свойству (строке) в MVVM. В MVVM все, что вам нужно, это отслеживать отдельные свойства (вверху, справа, внизу, справа).

Вы можете использовать конвертеры, как в: Как установить верхнее поле только в XAML? или Связывание только части свойства margin элемента управления WPF

Хотя привязанное свойство может работать. Я бы попытался провести рефакторинг вашего кода, чтобы вы не вносили изменения в пользовательский интерфейс. Вы должны обрабатывать как можно больше пользовательского интерфейса внутри проектной части файла. Я стараюсь использовать как можно меньше кодовых файлов xaml, потому что это вызывает проблемы с MVVM.

Вы не правы с этой частью:

var button = new Button();
button.Margin.Right = 10;

ошибка CS1612: невозможно изменить возвращаемое значение "System.Windows.FrameworkElement.Margin", поскольку оно не является переменной

Уже не является допустимым кодом, потому что Margin возвращает структуру и, следовательно, является типом значения. И поскольку он не является производным от DependencyObject, многие приемы DataBinding также не будут работать.

Я просто хотел дать правильное объяснение, иначе я бы сказал, что ваш первый ответ - практически единственный путь.

Другие вопросы по тегам