Ustawianie właściwości marginesu w kodzie

82
MyControl.Margin.Left = 10;

Błąd:

Nie można zmodyfikować wartości zwracanej „System.Windows.FrameworkElement.Margin”, ponieważ nie jest to zmienna

Giffyguy
źródło

Odpowiedzi:

138

Problem polega na tym, że Marginjest to właściwość, a jej type ( Thickness) jest typem wartości. Oznacza to, że kiedy uzyskujesz dostęp do właściwości, otrzymujesz kopię wartości z powrotem.

Nawet jeśli może zmienić wartość Thickness.Leftwłaściwości dla określonej wartości (grr ... Zmienne typy wartości nie powinien istnieć), nie byłoby zmienić margines.

Zamiast tego musisz ustawić Marginwłaściwość na nową wartość. Na przykład (przypadkowo ten sam kod, który napisał Marc):

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

Jako uwaga na temat projektowania bibliotek, zdecydowanie wolałbym, aby Thicknessbył niezmienny, ale z metodami, które zwracały nową wartość, która była kopią oryginału, ale z zastąpioną jedną częścią. Wtedy możesz napisać:

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

Nie martw się o dziwne zachowanie zmiennych typów wartości, ładne i czytelne, wszystko jedno wyrażenie ...

Jon Skeet
źródło
3
brawa za wyszukanie właściwego typu ... Przyznaję się do oszukiwania z var- ahem, przepraszam; Mam na myśli „używanie odpowiedniej funkcji językowej” ;-p
Marc Gravell
1
Pomogło to, że komunikat o błędzie zawierał w pełni kwalifikowaną nazwę typu. Dzięki szybkiej zakładce dla MSDN potrzebowałem tylko "msdn System.Windows.FrameworkElement.Margin" na pasku adresu, aby przejść na właściwą stronę ...
Jon Skeet
Marc, zvolkov odkrył nasz sekret! Okazało się, że zbyt łatwo było zdobyć 200 dziennie, więc pomyślałem, że postawię sobie większe wyzwanie i spróbuję zdobyć 2 najlepszych użytkowników. Dostanie "Marca" jako moderatora było tylko bonusem ...;)
Jon Skeet
Ale co z innymi z nas? Mam na myśli mnie? czy już wiedzą o scenariuszu „legionu”?
Marc Gravell
Czy mogę dodać, że jesteście przezabawni? Czy pracujesz razem poza StackOverflow czy coś? Jesteś taki przyjacielski - czuję się jak outsider, haha.
Giffyguy
41

MarginWłaściwość zwraca Thicknessstrukturę, z której Leftjest nieruchomość. Instrukcja kopiuje wartość struktury z Marginwłaściwości i ustawia Leftwartość właściwości w kopii. Pojawia się błąd, ponieważ ustawiona wartość nie zostanie z powrotem zapisana we Marginwłaściwości.

(Wcześniejsze wersje C # po prostu pozwoliłyby ci to zrobić bez narzekania, powodując wiele pytań w grupach dyskusyjnych i forach o to, dlaczego takie oświadczenie nie ma żadnego wpływu ...)

Aby ustawić właściwość, musisz pobrać Thicknessstrukturę z Marginwłaściwości, ustawić wartość i zapisać ją z powrotem:

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

Jeśli zamierzasz ustawić wszystkie marginesy, po prostu utwórz Thicknessstrukturę i ustaw je wszystkie naraz:

MyControl.Margin = new Thickness(10, 10, 10, 10);
Guffa
źródło
13

Marginzwraca strukturę, co oznacza, że ​​edytujesz kopię . Będziesz potrzebował czegoś takiego:

var margin = MyControl.Margin;
margin.Left = 10;
MyControl.Margin = margin;
Marc Gravell
źródło
(okrzyki, naprawione jakiś czas temu ... Spodziewam się, że potrzebujesz odświeżenia strony ;-p)
Marc Gravell
11

Można tego po prostu użyć

MyControl.Margin = new System.Windows.Thickness(10, 0, 5, 0);
LuckyLikey
źródło
4

Można by zgadywać (a mój WPF jest teraz trochę zardzewiały), że Margin pobiera obiekt i nie można go bezpośrednio zmienić.

na przykład

MyControl.Margin = new Margin(10,0,0,0);
Popiół
źródło
To nie działa: „System.Windows.FrameworkElement.Margin” jest „właściwością”, ale jest używany jako „typ”
Tor Klingberg
4

Aby skorzystać Thickness, musisz utworzyć / zmienić .NET frameworkwersję platformy projektu na 4.5. ponieważ ta metoda jest dostępna tylko w wersji 4.5. (Możesz także po prostu pobrać PresentationFramework.dll i podać odwołanie do tej biblioteki dll, bez tworzenia / zmiany pliku.NET framework wersji do 4.5).

Ale jeśli chcesz zrobić to prosto, możesz użyć tego kodu:

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

również

MyControl.Margin = new Padding(int all);

Jest to proste i nie wymaga żadnych zmian w Twoim projekcie

Daler Tursunov
źródło
3

W zależności od sytuacji możesz również spróbować użyć właściwości dopełniania tutaj ...

MyControl.Margin=new Padding(0,0,0,0);
Rishi
źródło
2

Margines = nowa Grubość (0, 0, 0, 0);

KalleP
źródło
Więcej wyjaśnień na temat twojego kodu byłoby miłe. Prosimy nie podawać tylko kodu pocztowego.
Jackyef,
0

Trochę niejasne jest, o co prosisz, ale aby wszystko było wygodne, możesz odziedziczyć własną Control i dodać właściwość z kodem sugerowanym przez Marc:

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

Następnie w kodzie klienta możesz napisać po prostu

MyImage img = new MyImage();
img.MarginLeft = 10;
MessageBox.Show(img.Margin.Left.ToString()); // or img.MarginLeft
Jan Turoň
źródło
wykorzystując dziedziczenie do rozwiązania tego problemu? Całkiem duży koszt, prawda?
LuckyLikey
@LuckyLikey zależy to od przypadku użycia: jeśli planujesz zmienić MerginLeftw wielu miejscach w projekcie, dziedziczenie pozwala uniknąć problemów projektowych. Oczywiście, jeśli jest to jedno miejsce w Twoim projekcie, wybrałbym akceptowaną odpowiedź.
Jan Turoň