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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12632079/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 05:35:16  来源:igfitidea点击:

How do I modify ONLY the right (or left, top, bottom) value of a WPF control's Margin property?

wpfxamlmvvmwpf-controlsmvvm-light

提问by bugged87

This is quite easy to do from code-behind:

这很容易从代码隐藏中完成:

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

In XAML, however, I'm limited to the following:

但是,在 XAML 中,我仅限于以下内容:

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

The problem with this is that now I've potentially overwritten the other margin values (i.e. left, top, bottom) by setting them to zero).

这样做的问题是,现在我可能通过将其他边距值(即左、上、下)设置为零来覆盖它们。

Is there any way to have XAML like the following?

有没有办法让 XAML 像下面这样?

<Button MarginRight="10" />

采纳答案by bugged87

An attached property could be used. In fact, this is exactly the purpose of attached properties: accessing parent element properties or adding additional functionality to a specific element.

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

For example, define the following class somewhere in your application:

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

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;
                }
            }
        }
    }
}

Now in your XAML all you must do is declare the following namespace:

现在在您的 XAML 中,您必须做的就是声明以下命名空间:

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

And then you can write XAML such as the following:

然后您可以编写 XAML,如下所示:

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





Alternatively, you can avoid using an attached property and instead write some slightly more lengthy XAML such as:

或者,您可以避免使用附加属性,而是编写一些稍长一些的 XAML,例如:

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

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

回答by kbo4sho88

Although an attatched property can work. I would try to refactor your code so you are not making UI changes in the the code behind. You should handle as much of the UI as you can inside the design side of the file. I try to use the codebehind of xaml files as little as possible because it causes issues with MVVM.

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

回答by Patrice Calvé

You could data bind the Margin to a property (string) in your MVVM. In your MVVM, all you need is to track the individual properties (top, right, bottom, right).

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

You can use converters as in: How to set a top margin only in XAML?or Binding only part of the margin property of WPF control

您可以使用转换器,如:How to set a top margin only in XAML? 仅绑定 WPF 控件的部分边距属性

回答by dowhilefor

You are wrong with this part:

这部分你错了:

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

error CS1612: Cannot modify the return value of 'System.Windows.FrameworkElement.Margin' because it is not a variable

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

Is already not valid code, because Margin returns a structand is therefore a value type. And because it doesn't derive from DependencyObject a lot of DataBinding tricks also won't work.

已经不是有效代码,因为 Margin 返回一个结构体,因此是一个值类型。并且因为它不是从 DependencyObject 派生的,所以很多 DataBinding 技巧也不起作用。

I just wanted to give a proper explanation, otherwise i would say your first answer is pretty much the only way.

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