在代码中设置保证金属性


81
MyControl.Margin.Left = 10;

错误:

无法修改'System.Windows.FrameworkElement.Margin'的返回值,因为它不是变量

Answers:


137

问题在于这Margin是一个属性,其类型(Thickness)是一个值类型。这意味着当您访问属性时,您将获得值的副本

即使您可以更改Thickness.Left特定值的属性值(grr ...可变值类型都不应该存在),也不会更改边距。

相反,您需要将Margin属性设置为新值。例如(碰巧与Marc编写的代码相同):

Thickness margin = MyControl.Margin;
margin.Left = 10;
MyControl.Margin = margin;

作为库设计的说明,如果它Thickness是不可变的,我会更喜欢它,但是使用的方法返回的是新值,该值是原始值的副本,但替换了一部分。然后,您可以编写:

MyControl.Margin = MyControl.Margin.WithLeft(10);

不用担心可变值类型的奇特行为,美观和可读,所有表达式...


3
查找实际类型表示荣誉...我承认与作弊var-抱歉,对不起;我的意思是“使用适当的语言功能” ;-p
Marc Gravell

1
错误消息包含完全限定的类型名称,这有帮助。有了MSDN的快速书签,我只需要在地址栏上输入“ msdn System.Windows.FrameworkElement.Margin”即可转到正确的页面...
Jon Skeet

Marc,zvolkov发现了我们的秘密!事实证明,每天获取200个用户太容易了,因此我认为自己要面对更多挑战,并尝试获得前2名用户。让“ Marc”担任主持人只是一个奖励……;)
Jon Skeet

但是我们其他人呢?我的意思是我?他们还知道“军团”剧本吗?
马克·格雷韦尔

我可以补充一下,你们很搞笑吗?您是否在StackOverflow之外合作?你们都很傻-这让我觉得自己像个局外人,哈哈。
Giffyguy

40

Margin属性返回一个Thickness结构,其中Left一个是属性。该语句的作用是从Margin属性复制结构值,并Left在副本上设置属性值。您会收到错误消息,因为您设置的值不会存储回该Margin属性中。

(早期版本的C#可以让您毫无抱怨地进行操作,这在新闻组和论坛中引发了很多问题,为什么这样的声明根本没有效果...)

要设置属性,您需要ThicknessMargin属性中获取结构,设置值并将其存储回去:

Thickness m = MyControl.Margin;
m.Left = 10;
MyControl.Margin = m;

如果要设置所有边距,只需创建一个Thickness结构并立即设置它们:

MyControl.Margin = new Thickness(10, 10, 10, 10);

13

Margin返回一个结构,这意味着您正在编辑副本。您将需要以下内容:

var margin = MyControl.Margin;
margin.Left = 10;
MyControl.Margin = margin;

(欢呼声,已经修复了一段时间……我希望您需要刷新页面;-p)
Marc Gravell

11

一个人可以简单地使用这个

MyControl.Margin = new System.Windows.Thickness(10, 0, 5, 0);

4

有人会猜测(并且我的WPF现在有点生锈)Margin占用了一个对象,无法直接更改。

例如

MyControl.Margin = new Margin(10,0,0,0);

这不起作用:“ System.Windows.FrameworkElement.Margin”是“属性”,但像“类型”一样使用
Tor Klingberg,2016年

4

要使用它,Thickness您需要将项目.NET framework平台版本创建/更改为4.5。因为此方法仅在4.5版中可用。(您也可以下载PresentationFramework.dll并提供对该DLL的引用,而无需创建/更改.NET framework版本为4.5。)

但是,如果您想这样做简单,则可以使用以下代码:

MyControl.Margin = new Padding(int left, int top, int right, int bottom);

MyControl.Margin = new Padding(int all);

这很简单,不需要对项目进行任何更改


3

根据情况,您也可以在此处尝试使用padding属性...

MyControl.Margin=new Padding(0,0,0,0);

2

保证金=新的厚度(0,0,0,0);


关于您的代码的更多解释将是不错的。请不要仅发布代码。
Jackyef

0

不清楚您要问的是什么,但是为了使事情变得舒适,您可以继承自己的Control并使用Marc建议的代码添加一个属性:

class MyImage : Image {
    private Thickness thickness;
    public double MarginLeft {
        get { return Margin.Left; }
        set { thickness = Margin; thickness.Left = value; Margin = thickness; }
    }
}

然后在客户端代码中,您可以编写

MyImage img = new MyImage();
img.MarginLeft = 10;
MessageBox.Show(img.Margin.Left.ToString()); // or img.MarginLeft

用继承来解决这样的问题?开销很大,不是吗?
LuckyLikey

@LuckyLikey取决于用例:如果您计划MerginLeft在项目中的多个位置进行更改,则继承可以避免设计问题。当然,如果这是您项目中的一个地方,我会选择接受的答案。
JanTuroň2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.