在代码中设置边距属性

89
MyControl.Margin.Left = 10;

Error:

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

9个回答

148
问题在于Margin是一个属性,而它的类型(Thickness)是一个值类型。这意味着当您访问该属性时,您会得到一个值的副本
即使您可以更改特定值的Thickness.Left属性的值(grr…可变值类型不应存在),它也不会更改边距。
相反,您需要将Margin属性设置为新值。例如(巧合的是,与Marc编写的代码相同):
Thickness margin = MyControl.Margin;
margin.Left = 10;
MyControl.Margin = margin;

作为图书馆设计的一条注释,我更希望 Thickness 是不可变的,但是有方法返回一个新值,该值是原始值的副本,但其中的一部分被替换。然后你可以这样写:
MyControl.Margin = MyControl.Margin.WithLeft(10);

不必担心可变值类型的奇怪行为,代码易读性好,所有内容都在一个表达式中...

4
感谢您查找实际类型...我得承认我使用了var这个“作弊”的东西-啊咳,抱歉;我是说“使用了一个适当的语言特性”;-p - Marc Gravell
1
错误信息包含完全限定类型名称这一点非常有帮助。通过快速在 MSDN 上添加书签,我只需要在地址栏中输入“msdn System.Windows.FrameworkElement.Margin”就可以进入正确的页面了... - Jon Skeet
Marc, zvolkov 发现了我们的秘密!原来一天内获得200分太容易了,所以我想给自己设定更大的挑战,尝试成为前两名用户。成为“Marc”的管理员只是额外的奖励... ;) - Jon Skeet
但是其他人呢?我的意思是我自己?他们知道“军团”脚本了吗? - Marc Gravell
我可以说你们很搞笑吗?你们在 StackOverflow 之外还一起工作吗?你们都这么亲密 - 这让我感觉自己像个局外人,哈哈。 - Giffyguy

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

(早期版本的C#允许您这样做而不发出警告,导致新闻组和论坛上出现很多关于为什么这样的语句根本没有效果的问题...)

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

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

如果你将要设置所有的边距,只需要创建一个Thickness结构并一次性设置它们:

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

“New Thickness”正是我在想要修改“Margin”和“Padding”属性时正在寻找的东西。我敢打赌这也适用于“BorderThickness”。谢谢! - k1dfr0std

17

Margin 返回一个结构体,这意味着你正在编辑一个副本。你需要像这样:

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

(欢呼声)已经修复了一段时间...我猜你需要刷新页面 ;-p - Marc Gravell

15

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

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

4

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

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

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

also

MyControl.Margin = new Padding(int all);

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

4

据我猜测(我的WPF现在有点生疏),Margin采用对象,不能直接更改。

例如:

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

这个不起作用:_'System.Windows.FrameworkElement.Margin'_ 是一个“属性”,但被用作了“类型”。 - Tor Klingberg
在 .NetFramework 中使用 Thickness: MyControl.Margin = new Thickness(10, 0, 0, 0); - Elyas Nategh

4

Margin = new Thickness(0, 0, 0, 0);


更多关于你的代码的解释会更好。请不要只是发布代码。 - Jackyef

0

不太清楚你在问什么,但为了让事情更方便,您可以继承自己的控件并添加一个具有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,那么继承可以避免设计问题。当然,如果这只是你的项目中的一个地方,我会选择接受的答案。 - Jan Turoň

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接