Đặt thuộc tính Margin trong mã


81
MyControl.Margin.Left = 10;

Lỗi:

Không thể sửa đổi giá trị trả về của 'System.Windows.FrameworkElement.Margin' vì nó không phải là một biến

Câu trả lời:


137

Vấn đề là đó Marginlà một thuộc tính, và kiểu ( Thickness) của nó là một kiểu giá trị. Điều đó có nghĩa là khi bạn truy cập thuộc tính, bạn sẽ nhận được bản sao của giá trị.

Mặc dù bạn có thể thay đổi giá trị của thuộc Thickness.Lefttính cho một giá trị cụ thể (không nên tồn tại các loại giá trị có thể thay đổi grr ...), nó sẽ không thay đổi lề.

Thay vào đó, bạn sẽ cần đặt thuộc Margintính thành một giá trị mới. Ví dụ (trùng hợp là mã giống như Marc đã viết):

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

Như một lưu ý cho thiết kế thư viện, tôi sẽ rất thích nó nếu Thicknesslà bất biến, nhưng với các phương thức trả về giá trị mới là bản sao của bản gốc, nhưng với một phần được thay thế. Sau đó, bạn có thể viết:

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

Không phải lo lắng về hành vi kỳ quặc của các loại giá trị có thể thay đổi, đẹp và dễ đọc, tất cả một biểu thức ...


3
kudos để tra cứu loại thực tế ... Tôi thú nhận là đã gian lận với var- ahem, xin lỗi; Ý tôi là "sử dụng một đặc điểm ngôn ngữ thích hợp" ;-p
Marc Gravell

1
Nó đã giúp thông báo lỗi chứa tên loại đủ điều kiện. Với một bookmark nhanh chóng cho MSDN, tôi chỉ cần "MSDN System.Windows.FrameworkElement.Margin" trên thanh địa chỉ để đến được trang đúng ...
Jon Skeet

Marc, zvolkov đã khám phá ra bí mật của chúng tôi! Hóa ra là quá dễ dàng để đạt được 200 trong một ngày, vì vậy tôi nghĩ rằng mình sẽ đặt ra cho mình nhiều thử thách hơn và cố gắng đạt được 2 người dùng hàng đầu. Bắt "Marc" như một người điều hành chỉ là một tiền thưởng ...;)
Jon Skeet

Nhưng những người khác trong chúng ta thì sao? Tôi có nghĩa là tôi? họ đã biết về kịch bản "quân đoàn" chưa?
Marc Gravell

Tôi có thể nói thêm rằng các bạn rất vui nhộn? Bạn có làm việc cùng nhau bên ngoài StackOverflow hay gì đó không? Tất cả các bạn đều rất tuyệt - nó khiến tôi cảm thấy như một người ngoài cuộc, haha.
Giffyguy

40

Các Margintài sản trả về một Thicknesscấu trúc, trong đó Leftlà một tài sản. Những gì câu lệnh làm là sao chép giá trị cấu trúc từ thuộc Margintính và thiết lập Leftgiá trị thuộc tính trên bản sao. Bạn gặp lỗi vì giá trị bạn đặt sẽ không được lưu trữ trở lại thuộc Margintính.

(Các phiên bản trước của C # sẽ cho phép bạn làm điều đó mà không cần phàn nàn, gây ra rất nhiều câu hỏi trong các nhóm tin và diễn đàn về lý do tại sao một tuyên bố như vậy không có tác dụng gì cả ...)

Để đặt thuộc tính, bạn sẽ cần lấy Thicknesscấu trúc từ thuộc Margintính, đặt giá trị và lưu trữ lại:

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

Nếu bạn định đặt tất cả các lề, chỉ cần tạo một Thicknesscấu trúc và đặt tất cả chúng cùng một lúc:

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

13

Marginđang trả về một cấu trúc, có nghĩa là bạn đang chỉnh sửa một bản sao . Bạn sẽ cần một cái gì đó như:

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

(chúc mừng, đã sửa một thời gian trước ... Tôi hy vọng bạn cần làm mới trang ;-p)
Marc Gravell

11

Người ta có thể đơn giản sử dụng cái này

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

4

Người ta có thể đoán rằng (và WPF của tôi bây giờ hơi cũ) rằng Margin lấy một đối tượng và không thể thay đổi trực tiếp.

ví dụ

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

Đây không phải làm việc: 'System.Windows.FrameworkElement.Margin' là một 'tài sản' nhưng được sử dụng như một 'loại'
Tor Klingberg

4

Để sử dụng, Thicknessbạn cần tạo / thay đổi .NET frameworkphiên bản nền tảng dự án của mình thành 4.5. vì phương pháp này chỉ có trong phiên bản 4.5. (Ngoài ra, bạn chỉ có thể tải xuống PresentationFramework.dll và cung cấp tham chiếu cho dll này mà không cần tạo / thay đổi .NET frameworkphiên bản của bạn thành 4.5.)

Nhưng nếu bạn muốn làm điều này đơn giản, Bạn có thể sử dụng mã này:

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

cũng thế

MyControl.Margin = new Padding(int all);

Điều này rất đơn giản và không cần bất kỳ thay đổi nào đối với dự án của bạn


3

Tùy thuộc vào tình hình, bạn cũng có thể thử sử dụng thuộc tính padding tại đây ...

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

2

Margin = độ dày mới (0, 0, 0, 0);


Giải thích thêm về mã của bạn sẽ rất hay. Vui lòng tránh chỉ đăng mã.
Jackyef

0

Có một chút không rõ ràng bạn đang yêu cầu điều gì, nhưng để làm cho mọi thứ trở nên thoải mái, bạn có thể kế thừa Quyền kiểm soát của riêng mình và thêm một thuộc tính với mã mà Marc gợi ý:

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

Sau đó, trong mã khách hàng, bạn chỉ có thể viết

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

sử dụng kế thừa để giải quyết vấn đề như vậy? Khá lớn, phải không?
LuckyLikey

@LuckyLikey nó phụ thuộc vào trường hợp sử dụng: nếu bạn định thay đổi MerginLeftnhiều vị trí trong dự án, việc kế thừa sẽ tránh được các vấn đề về thiết kế. Tất nhiên, nếu đây là một nơi duy nhất trong dự án của bạn, tôi sẽ chọn câu trả lời được chấp nhận.
Jan Turoň
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.