Entwickler-Ecke
WPF / Silverlight - 2 Slider voneinander abhängig, großes Problem beim atualisie
zappo - Di 20.10.09 01:19
Titel: 2 Slider voneinander abhängig, großes Problem beim atualisie
Hallo Leute,
das hier ist vermutlich ein einigermassen triviales Problem, aber ich komme schlicht nicht auf die Lösung.
In einer Anwendung habe ich 2 Slider, diese sind voneinander abhängig in der Form, das eine Änderung egal welcher der Slider die Änderung der Werte Minimum, Maximum, + der Selection Start und End Werte beider Slider zur Folge hat...
Nun das Problem,
ich habe eine Funktion
C#-Quelltext
1: 2: 3: 4:
| public void CalcSliderValues() { ...... } |
In welchem die Werte für die Slider errechnet werden, diese schreibe ich dann gleich in eigenschaften der klasse, an welche ich wiederrum im WPF die Slider gebunden habe, soweit so gut, mit nur einem Slider funktioniert das auch wunderbar... Der Knackpunkt liegt in meinem Aufruf der Funktion, denn die findet statt, sobald sich das "Value" eines Sliders ändert.. und zwar folgendermassen
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| public int slider2 { get { return _slider2_value; } set { _slider2_value = value; CalcSliderValues() OnPropertyChanged("slider2"); } } public int slider1 { get { return _slider1_value; } set { _slider1_value = value; CalcSliderValues() OnPropertyChanged("slider1"); } } |
Mein Problem ist also, das die Slider sich beim aktualisieren der Werte immer wieder gegenseitig aktualisieren, was zu einem StackOverflow führt... wie kann ich dies umgehen? Kann mir jemand helfen??
Gruß
Sebastian
P.S.
Danke noch einmal, speziell an Kha, für die bisher gegebenen Tips, ihr habt mir als Neuling damit schon so manches erleichtert...
Edit: S***... Thread im falschen Unterforum, glaube hätte in C# gehört.. könnte ein Mod das verschieben? Ist glaub ich besser als noch einmal neu posten...
Kha - Di 20.10.09 19:47
Ich sehe drei Möglichkeiten:
- Je nach Komplexität dieser Beziehung (bzw. du das Gefühl hast, im ViewModel Redundanz zu haben) könnte man das VM auf eine Property reduzieren und für den zweiten Slider einen Value Converter dazwischen schalten. Überhaupt haben Namen wie "Slider" eher wenig im VM zu suchen ;) .
- Die beste Lösung dürfte sein: OnPropertyChanged aus den Settern entfernen, dafür beide in CalcSliderValues einfügen.
- Wenn du die vorherige Lösung verallgemeinern bzw. komplett auf INotifyPropertyChanged verzichten willst, schau dir unbedingt das hier an :shock: :
An easier way to manage INotifyPropertyChanged [http://ayende.com/Blog/archive/2009/08/08/an-easier-way-to-manage-inotifypropertychanged.aspx]
Bringt dir so zwar noch nichts, ich habe die Klasse aber noch etwas erweitert:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55:
| public class Observable<T> : INotifyPropertyChanged { private T value;
public Observable() {
}
public Observable(T value) { this.value = value; }
public T Value { get { return value; } set { if (object.Equals(Value, value)) return;
SetInternal(value); ChangedExternal(this, new PropertyChangedEventArgs("Value")); } }
public void SetInternal(T value) { if (object.Equals(value, this.value)) return;
this.value = value; PropertyChanged(this, new PropertyChangedEventArgs("Value")); }
public static implicit operator T(Observable<T> val) { return val.value; }
public Observable<U> MapTwoWay<U>(Func<T, U> map, Func<U, T> mapReverse) { var other = new Observable<U>(map(Value));
ChangedExternal += delegate { other.SetInternal(map(Value)); }; other.ChangedExternal += delegate { SetInternal(mapReverse(other.Value)); };
return other; }
public event PropertyChangedEventHandler PropertyChanged = delegate { }; public event PropertyChangedEventHandler ChangedExternal = delegate { }; } |
SetInternal ermöglicht genau das, was du brauchst: Die Änderung wird über INotifyPropertyChanged an die View weitergegeben, aber nicht an andere Observables. MapTwoWay ist gleich ein praktisches Beispiel dafür.
Benutzung:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| Observable<int> Value1 { get; private set; } Observable<int> Value2 { get; private set; }
...
ctor:
Value1 = new Observable<int>(); Value2 = Value1.MapTwoWay(ConvertValue1ToValue2, ConvertValue2ToValue1); |
Gut, das war eher grob skizziert und vielleicht eher die berühmte Spatzenkanone, aber solange ich nie mehr IPropertyValueChanged selbst implementieren muss, ist es mir recht ;) .
zappo hat folgendes geschrieben : |
Danke noch einmal, speziell an Kha, für die bisher gegebenen Tips, ihr habt mir als Neuling damit schon so manches erleichtert... |
:D
zappo hat folgendes geschrieben : |
Thread im falschen Unterforum, glaube hätte in C# gehört |
Gute Frage. Eigentlich geht es um allgemeine Programm-Logik, aber da sich das Problem in dieser Form sowieso nur in WPF/SL stellt, passt das schon so :) .
zappo - Mi 21.10.09 01:45
HM!!!
Sehr interessanter Ansatz das was du da zeigst.... für meinen Teil wahrscheinlich wirklich die Spatzenkanone.. .aber das werde ich mir auf jeden Fall gut merken!!!
Was die Slider angeht.. die slider selber hängen da auch nicht drin, das sind natürlich nur die Werte, an welche diese gebunden werden.... (das darf ich, oder? :-) )
Gelöst habe ich es schliesslich denkbar einfach...
zusätzliche Eigenschaft "sync eingeführt, diese wird in der CalcSliderValues() gesetzt,
C#-Quelltext
1: 2: 3: 4: 5: 6:
| public void CalcSliderValues() { _slider_sync = false; .... Berechnungen; _slider_sync = true; } |
In den Eigenschaften welche ich von hier aus setze dann jeweils im Setter abgefragt bevor bei Aktualisierung ausgeführt
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| public double _sld_value { get { return sld_value; } set { sld_value = value; OnPropertyChanged("_sld_value"); if (_slider_sync == true) { CalcSliderValues(); } } } |
Schon aktualisieren Sie sich nicht mehr gegenseitig bis in alle Ewigkeit! ;)
Danke wie gesagt trotzdem für die Hilfe.. deinen Ansatz werde ich mir gleich mal Bookmarken und bei einem anderem Problem ausprobieren! ;)
Gruß Sebastian
Kha - Mi 21.10.09 15:28
Da finde ich meinen zweiten Vorschlag aber ehrlich gesagt passender und gleichzeitig genauso simpel. Was passiert bei dir, wenn CalcSliderValues eine Exception wirft ;) ?
zappo hat folgendes geschrieben : |
die slider selber hängen da auch nicht drin, das sind natürlich nur die Werte, an welche diese gebunden werden |
Klar. Aber trotzdem erfüllen diese zwei Properties ja einen Zweck, nach dem sie benannt werden sollten. Control-Namen im VM kommen mir einfach merkwürdig vor.
zappo - Mi 21.10.09 19:02
Kha hat folgendes geschrieben : |
Da finde ich meinen zweiten Vorschlag aber ehrlich gesagt passender und gleichzeitig genauso simpel. Was passiert bei dir, wenn CalcSliderValues eine Exception wirft ;) |
Ja..ok.. da würde meine Lösung ein Problem darstellen! Keine Frage... :/ Deine Zweite hatte ich auch total aus den Augen verloren als ich die Dritte gesehen habe! ;)
*grins*
Allerdings ist es ziemlich unwahrscheinlich das mir CalcSliderValues eine Exception wirft.. das gute Stück hat ja nicht viel zu tun.. trotzdem.. Recht hast du, werde umschwenken!
Kha hat folgendes geschrieben : |
zappo hat folgendes geschrieben : | die slider selber hängen da auch nicht drin, das sind natürlich nur die Werte, an welche diese gebunden werden | Klar. Aber trotzdem erfüllen diese zwei Properties ja einen Zweck, nach dem sie benannt werden sollten. Control-Namen im VM kommen mir einfach merkwürdig vor. |
Ja.. ok.. Eine Sache der Konventionen.. daran muss ich mich wohl noch gewöhnen.. stimmt auch... besser jetzt, als gar nicht mehr..
Danke dir für den Hinweis! :-p
Moderiert von Christian S.: Quote-Tag repariert
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!