Как изменить ТОЛЬКО правое (или левое, верхнее, нижнее) значение свойства 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 также не будут работать.
Я просто хотел дать правильное объяснение, иначе я бы сказал, что ваш первый ответ - практически единственный путь.