Laden...

Property an bool binden (WPF)

Erstellt von JonnyJohnson vor 11 Jahren Letzter Beitrag vor 11 Jahren 3.419 Views
J
JonnyJohnson Themenstarter:in
17 Beiträge seit 2012
vor 11 Jahren
Property an bool binden (WPF)

Hallo,

ich schlage mich mit einer (sicher dämlichen) Frage rum:
Ich habe ein Overlay in WPF und das hat eine Eigenschaft IsOverlayEnabled. Setzt man dieses auf true, überblendet es die ganze momentane Anzeige. Nun soll die Eigenschaft aber einen boolschen Wert gebunden werden, der sich im Code ändert.
Habe da schon einiges versucht, allerdings reagiert das Element nicht auf die Änderung und ich weiß nicht wieso.

IsOverlayEnabled="{Binding Path=IsOverlay}" oder IsOverlayEnabled="{Binding IsOverlay}" bewirken da nichts.
Auf ner anderen Seite hab ich gelesen, dass man evtl. noch dieses IPropertyChanged einbauen müsste, ist das vllt der springende Punkt?

MfG

3.511 Beiträge seit 2005
vor 11 Jahren

Hallo,

ja du musst INotifyPropertyChanged implementieren. Schau dir dazu mal Beispiele zum Thema MVVM an. Dann wirst du auch sicherlich weiterkommen.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

A
15 Beiträge seit 2012
vor 11 Jahren

Man könnte INotifyPropertyChanged einsetzen oder eine dependency property erstellen.

Hier mal ein Beispiel für INotifyPropertyChanged:


public class myClass : INotifyPropertyChanged
    {
        private int var;
        public event PropertyChangedEventHandler PropertyChanged;

        public int Var
        {
            get { return var; }
            set 
            { 
                var = value;
                OnChanged("Var");
            }
        }

        private void OnChanged(string propertyName) {
            if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Die OnChanged-Methode vereinfacht, das Auslösen von PropertyChanged, wenn man viele Properties hat. Unschön finde ich, dass man den Namen, der Eigenschaft als Zeichenkette angeben muss, aber ich kenne keine andere Lösung dafür.

1.552 Beiträge seit 2010
vor 11 Jahren

Hallo Ace86,

Unschön finde ich, dass man den Namen, der Eigenschaft als Zeichenkette angeben muss

Es gibt MVVM-Frameworks wie Cinch bei denen es über Lambda-Expressions geht. Damit fällt das Refaktorisieren leichter. Tools wie ReSharper sind jedoch auch in der Lage die Strings in OnChanged zu refaktorisieren.

Man könnte INotifyPropertyChanged einsetzen oder eine dependency property erstellen

DP können nur in Klassen eigesetzt werden welche von DependencyObject erben, da ansonsten GetValue und SetValue fehlen. Damit haben sie in einer ViewModel Klasse nichts verloren.

Bindings funktionieren nur an DependencyProperties.
Jedoch kann von allen public und/oder static Properties gebunden werden.

Gruß,
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

A
15 Beiträge seit 2012
vor 11 Jahren

DP können nur in Klassen eigesetzt werden welche von DependencyObject erben, da ansonsten GetValue und SetValue fehlen. Damit haben sie in einer ViewModel Klasse nichts verloren.

Im ersten Beitrag steht nicht, dass es im Zusammenhang mit MVVM verwendet wird. Ich wollte die DPs auch nur als weitere Möglichkeit nennen.

Es gibt MVVM-Frameworks wie Cinch bei denen es über Lambda-Expressions geht.

gut zu wissen

1.552 Beiträge seit 2010
vor 11 Jahren

Im ersten Beitrag steht nicht, dass es im Zusammenhang mit MVVM verwendet wird

Ich denke in WPF kann davon ausgegangen werden, dass minimales MVVM betrieben wird, da man ansonsten wieder bei derselben Technologie wie WinForms ist.

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

J
JonnyJohnson Themenstarter:in
17 Beiträge seit 2012
vor 11 Jahren

Erst mal Danke für die ersten Vorschläge.
Ich bin ja auch noch ganz am Anfang 😉 von daher ist das MVVM noch nicht ganz umgesetzt.
Ich hab allerdings nach wie vor das Problem, dass sich die Property vom XAML Bauteil nicht mitändert. Habe eine INstanz der Klasse erzeugt

public MyClass bla = new MyClass();

und ändere an gegebener Stelle den Wert

bla.Overlay = true;

aber trotzdem passiert nichts.

In der Baumstruktur im Debugger steht bei PropertyChanged stets

null

.

Das Binding versucht mit

IsOverlayEnabled="{Binding LoadingScreenOverlayEnable}"

oder mit weiteren Pfadangaben zur Instanz oder mit Projektname. Beim Debuggen wird der Wert im Designer (mit der Maus über die Bindingzuweisung fahren) auch richtig angezeigt, nur die Wirkung der Zuweisung (IsOverlayEnabled steht im Debugger unweigerlich auf

false

) zeigt sich nicht.

U
1.688 Beiträge seit 2007
vor 11 Jahren

Habe eine INstanz der Klasse erzeugt und ändere an gegebener Stelle den Wert, aber trotzdem passiert nichts.

[Hinweis] Wie poste ich richtig? 5

J
JonnyJohnson Themenstarter:in
17 Beiträge seit 2012
vor 11 Jahren
public class MyClass : INotifyPropertyChanged

ist dabei wie oben aufgebaut.

3.511 Beiträge seit 2005
vor 11 Jahren

Setze den BindingMode mal auf TwoWay.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

J
JonnyJohnson Themenstarter:in
17 Beiträge seit 2012
vor 11 Jahren

TwoWay hilft leider nicht 😦

U
1.688 Beiträge seit 2007
vor 11 Jahren

Hallo,

public class MyClass : INotifyPropertyChanged  

ist dabei wie oben aufgebaut.

es ist nicht so fein, dies nachträglich hinzuzufügen.

Auch kann man aus diesen Bruchstücken wie "false" überhaupt nichts sinnvolle unternehmen.

Wo wird die Klasse erzeugt? Wie denkst Du zu erreichen, dass Deine erzeugt Instanz überhaupt benutzt wird? Wie erfolgt die Bindung? Was ist "bla.Overlay", was "LoadingScreenOverlayEnable"?

J
JonnyJohnson Themenstarter:in
17 Beiträge seit 2012
vor 11 Jahren

Habs hinzugefügt, weil Editieren nicht möglich war.

IsOverlayEnabled ist die Eigenschaften eines Ladebildschirms, steht das auf "true" überdeckt es das ganze Window (oder Control, je nach dem). Diese Einstellung ist anfangs auf "false" gesetzt. Bei einem Buttonklick soll eine Anfrage per Backfgroundworker gestartet werden. Während der Anfrage soll die GUI gesperrt sein (IsOverlayEnabled sol true werden), jedoch entsteht durch das Überblendmodul nicht der Eindruck, dass alles abgeschmiert wäre, falls der Backgroundworker lange auf Daten warten muss.
Daher soll die Eigenschaft IsOverlayEnabled an ein bool im Code gebunden werden, welcher public gesetzt werden kann. Baut man das ganze also ein, setzt man nur an einer Stelle diesen bool auf true und der Rest passiert von alleine.
Das soll durch das Binding passieren, was bei mir aber nicht hinhaut, da die EIgenschaft IsOVerlayEnabled nicht darauf reagiert.

"bla" ist die Instanz der Klasse "MyClass", über die der bool-Wert gesetzt werden soll.
"LoadingScreenOverlayEnable" ist nur ein weiterer bool-Wert zum Testen, da es bis jetzt mit der PropertyChanged-Variante nicht klappt. Hiermit klappts aber genau so wenig.

Ich hoffe das ganze ist nun etwas klarer.

U
1.688 Beiträge seit 2007
vor 11 Jahren

Ich hoffe das ganze ist nun etwas klarer.

Leider nein, da Du noch immer nicht die wirklich relevanten Code-Teile gepostet hast.

J
JonnyJohnson Themenstarter:in
17 Beiträge seit 2012
vor 11 Jahren

Welchen Teil möchtest du denn haben?

5.657 Beiträge seit 2006
vor 11 Jahren

Hi JonnyJohnson,

versuch dich doch mal in die Leute reinzuversetzen, die dir hier helfen wollen. Was nutzt uns denn der Code, wo du irgendeine Variable zuweist? Du mußt doch am besten wissen, was relevant ist und was nicht! Es reicht eben nicht, irgendwelche unzusammenhängende Codeschnipsel zu posten, sondern es sollte uns helfen, dein Problem nachzuvollziehen.

Christian

Weeks of programming can save you hours of planning

C
258 Beiträge seit 2011
vor 11 Jahren

jedoch entsteht durch das Überblendmodul nicht der Eindruck, dass alles abgeschmiert wäre

Hilft dir jetzt bei deinem Problem nicht weiter aber wieso denkst du das es besser ist das Control einfach zu überblenden ?

Also wenn ein programm bei mir für 5 sekunden ein starres overlay anzeigt entsteht genauso der eindruck das alles abgeschmirt ist. Warum teilst du dem User nicht einfach mit wie weit deine Verarbeitung ist und sperrst die Controls einfach per Enabled = false;

J
JonnyJohnson Themenstarter:in
17 Beiträge seit 2012
vor 11 Jahren

Gut, versuchen wirs mal so:

Ich habe in der XAML-Datei als erstes Element (nach dem xlms:-Definitionen) folgendes:

<LoadingSection IsOverlayEnabled="{Binding myclass.Overlay, Mode=TwoWay}" Name="MainOverlay"> (LaodingSection ist dabei ein CustomControl, was bei IsOverlayEnabled = true das Parent überdeckt, bei Bedarf Buttons und eine Fortschrittsanzeige darstellt).
Die Eigenschaft IsOverlayEnabled kann hierbei true oder false sein. Der zugehörige bool-Wert soll ein public-Property sein, der Rest private.

Im Codebehind habe ich die Klasse


public class MyClass : INotifyPropertyChanged
        {
            private bool _overlay;
            public event PropertyChangedEventHandler PropertyChanged;

            public bool Overlay
            {
                get { return _overlay; }
                set
                { 
                _overlay = value;
                OnChanged("Overlay");
                }
            }
            public void OnChanged(string propertyName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

Welche ich per

private MyClass _myOverlay = new MyClass(); 

zu Beginn instanziiere. Klickt der Benutzer nun auf einen Button, soll die Eigenschaft IsOverlayEnabled auf true gesetzt werden für ein paar Sekunden und nach Ablauf eines Timers wieder auf false. Daher das Binding.

Nun sollte ja (den Erwartungen nach) ein Event auftreten, wenn ich _myOverlay.Overlay ändere, richtig? Durch das Binding sollte dann auch eigentlich IsOverlayEnabled davon Wind bekommen und entsprechend reagieren, tuts aber nicht.

Man könnte sicherlich alles deaktivieren, aber es ist gedacht da auch noch weitere Dinge hinzuzufügen, wobei sich eben die LoadingSection am besten dabei macht. 😕 Da ohne weitere Einstellung bei der LoadingSection sich auch noch was bewegt, entsteht der Eindruckt der abgeschmierten Anwendung eben auch nicht. 😃

5.657 Beiträge seit 2006
vor 11 Jahren

Hi JonnyJohnson,

wenn du eine Variable namens _myOverlay setzt, dann solltest du auch nicht gegen eine Eigenschaft namens myclass binden. Falls das überhaupt eine Eigenschaft ist, denn binden geht natürlich nur mit Eigenschaften. Wenn es sich um einen DataBinding-Fehler handelt, wird der auch im Ausgabefenster angezeigt, evtl. solltest du dort mal schauen was passiert.

Christian

Weeks of programming can save you hours of planning

J
JonnyJohnson Themenstarter:in
17 Beiträge seit 2012
vor 11 Jahren

Oh, das hatte ich falshc zusammenkopiert.
Ich binde mit IsOverlayEnabled="{Binding _myOverlay.Overlay, Mode=TwoWay}" und auch in der Ausgabe kommt kein Fehler...

5.657 Beiträge seit 2006
vor 11 Jahren

Hi JonnyJohnson,

so wie ich das sehe, ist _myOverlay ein privates Feld. Mach eine öffentliche Eigenschaft daraus, dann sollte es funktionieren. Es müßte meines Erachtens auch eine Fehlermeldung im Ausgabefenster stehen, die etwas ähnliches besagt. Am besten beliest du dich mal gezielt nach den Möglichkeiten und den Einschränkungen des DataBindings.

Christian

Weeks of programming can save you hours of planning

T
50 Beiträge seit 2010
vor 11 Jahren

Hast Du die Klasse auch an den DataContext gebunden? Sonst weiß er natürlich nicht, worauf er zugreifen soll.

this.DataContext = this._myOverlay;
J
JonnyJohnson Themenstarter:in
17 Beiträge seit 2012
vor 11 Jahren

So, nun gehts. 😃
Mit


IsOverlayEnabled="{Binding Path=Overlay, Mode=TwoWay}" Name="MainOverlay"

und nach der Instanziierung durch


MainOverlay.DataContext = _myOverlay;

liest er alles richtig aus und das Overlay reagiert, wie es soll 😃

Danke.