如何仅修改WPF控件的Margin属性的右侧(或左侧,顶部,底部)值?

时间:2012-09-28 00:42:33

标签: wpf xaml mvvm wpf-controls mvvm-light

从代码隐藏中可以很容易地做到这一点:

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 个答案:

答案 0 :(得分:11)

可以使用附加属性。实际上,这正是附加属性的目的:访问父元素属性或向特定元素添加其他功能。

例如,在应用程序的某处定义以下类:

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>

答案 1 :(得分:1)

虽然一个attatched属性可以工作。我会尝试重构您的代码,这样您就不会在后面的代码中进行UI更改。您应该尽可能多地处理文件设计方面的UI。我尝试尽可能少地使用xaml文件的代码隐藏,因为它会导致MVVM出现问题。

答案 2 :(得分:1)

您可以将Margin数据绑定到MVVM中的属性(字符串)。在MVVM中,您只需跟踪各个属性(顶部,右侧,底部,右侧)。

您可以使用转换器,如:How to set a top margin only in XAML?Binding only part of the margin property of WPF control

答案 3 :(得分:0)

这部分你错了:

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

错误CS1612:无法修改返回值   'System.Windows.FrameworkElement.Margin'因为它不是变量

已经不是有效代码,因为Margin返回struct因此是值类型。而且因为它不是从DependencyObject派生出来的,所以很多DataBinding技巧也行不通。

我只是想给出正确的解释,否则我会说你的第一个答案几乎是唯一的方法。