How do I modify ONLY the right (or left, top, bott

2019-02-06 10:31发布

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:

<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?

<Button MarginRight="10" />

4条回答
Explosion°爆炸
2楼-- · 2019-02-06 11:14

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:

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

And then you can write XAML such as the following:

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



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

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

查看更多
劳资没心,怎么记你
3楼-- · 2019-02-06 11:22

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

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

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

查看更多
倾城 Initia
4楼-- · 2019-02-06 11:24

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).

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

查看更多
贪生不怕死
5楼-- · 2019-02-06 11:34

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.

查看更多
登录 后发表回答