Laden...

Mehrere UserControls mit jeweils verschiedenem DataContext

Erstellt von NOFX vor 7 Jahren Letzter Beitrag vor 7 Jahren 4.377 Views
N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren
Mehrere UserControls mit jeweils verschiedenem DataContext

Hi,

ich versuche mich gerade an WPF mit MVVM und habe mich auf dieses Beispiel gestürzt, was halbwegs überschaubar eine - mMn - verständliche und gute Einführung ist: The World's Simplest C# WPF MVVM Example

Das Proble bei der Umsetzung habe ich jetzt damit, dass ich gerne mehrere Views mit unterschiedlichen DataContext erstellen würde, die alle auf Tabs in einem Fenster liegen. Hier wird jetzt "global" der DataContext mit

<Window.DataContext>
        <ViewModel:Presenter/>
    </Window.DataContext>

festgelegt. Eine Verschieben der Zuweisung des DataContext in den Aufruf des UserControls

<View:ConverterControl DataContext="ViewModel:Presenter"/>

bewirkt, dass es so auf jeden Fall nicht mehr funktioniert.

Wie kann ich also unterschiedliche UserControls als View mit jeweils eigenen DataContext nutzen?

R
228 Beiträge seit 2013
vor 7 Jahren

Dein "MainViewModel" ist da schon richtig. Du könntest über dein MainViewModel eine Auflistung von mehreren "TabViewModels" nach außen geben. Jedes ViewModel entspricht dabei einem Tab bzw. einem UserControl.

Dein TabControl bindest du dann an diese Auflistung.

Nun musst du festlegen, welches UserControl zu welchem ViewModel gehört.

Dazu legst du ein DataTempalte pro TabView/TabViewModel an:


<DataTemplate DataType="{x:Type :TabViewModel1l}">
    <vw:View1 />
  </DataTemplate>

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Bisher habe ich noch kein MainViewModel, da hier im Moment keine Daten o.ä. vorhanden sind.

Wie müsste die Auflistung darin denn aussehen? Hast du vielleicht ein Beispiel?

Danke und Gruß,
Fabian | NOFX

5.299 Beiträge seit 2008
vor 7 Jahren

Ein Beispiel eines Viewmodels zu posten ist meist nicht sinnvoll - bei Wpf müssen ja alle Elemente MainWindow, UserControls, MainViewmodel SubViewmodels - das muss ja alles zusammenpassen und aufeinander abgestimmt sein - sonst siehst du garnix.

Du kannst dir mal Grundlagen - MVVM-Anwendungs-Struktur angucken, das ist ein System, was funzt.
Es kommen da auch MainViewmodel, SubViewmodel, ucls und TabControls vor, aber dennoch wirds wahrscheinlich immer noch nur teilweise auf deine Problemstellung übertragbar sein.

Weil es ist ein Konglomerat eiglich unabhängiger Beispiele, während bei dir die Teile vmtl. in einem sinnvollen Zusammenhang miteinander stehen.
Aber guck ma rein, was draus lernen kann man wohl fast immer.

Der frühe Apfel fängt den Wurm.

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

In dem Beispiel ist nur ein DataContext gegeben. Grundsätzlich habe ich mehrere UserControls, die ja einen eigenen DataContrxt brauchen.

Ich habe jetzt ein MainViewModel erzeugt, indem ich die einzelnen ViewModels als Properties habe. Das funktioniert auf jeden Fall, danke für den Tipp, Rioma!

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Um nicht direkt wieder ein neues Thema zu eröffnen: Ich habe jetzt in einem der UserControls ein DataGrid, in dem ich Daten anzeigen und ändern kann, die in einer ObservableCollection im ViewModel hinterlegt sind.

Die Frage ist jetzt: Ich nutze Daten aus dieser ObservableCollection um mir Positionen für geometrische Objekte zu berechnen, die ich wieder als Property im ViewModel zur Verfügung stelle. Wie kann ich das PropertyChanged Event der Geometrie auslösen, wenn sich die ursprüngliche ObservableCollection ändert?

Binde ich geometrische Eigenschaften direkt an die ObservableCollection des DataGrids klappt das jetzt schon, nur müssen diese i.A. noch umgerechnet werden.

5.299 Beiträge seit 2008
vor 7 Jahren

ich hab bei sowas immer Schwierigkeiten zu folgen.
Ewa was verstehst du unter Geometrie, und Eigenschaften der Geometrie an eine OC zu binden?

Die Wpf Geometry-Klasse kannst du nicht meinen, die hat kein PropertyChanged-Event (oder?)

jdfs. wenns dich interessiert kannste mal gugge, was ich einstens mit Wpf-Geometry-Dinger gebastelt und gebunden hab: Linien, Figuren, Formen.

Was anneres, mit mehr Bewegung hier: Kein Pong

Der frühe Apfel fängt den Wurm.

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Mit Geometrien meine ich Größe und Position von Elipsen.

In meiner ObservableCollection für das DataGrid sind relative Positionen, die ich umrechne und wieder als ObservableCollection für die geometrischen Objekte zur Verfügung stelle.

Ändere ich jetzt im DataGrid etwas, wird das korrekt in die Collection übernommen, nur wird das PropertyChanged Event ja nur für die erste Collection angestoßen, sodass die geometrischen Objekte sich nicht neu positionieren.

5.299 Beiträge seit 2008
vor 7 Jahren

In meiner ObservableCollection für das DataGrid sind relative Positionen.... Das ist ungeeignet, denn "relative Positionen" haben kein NotifyPropertyChanged-Event.
In deiner OC sollten Objekte sein, die PositionsAngaben als geeignete Properties haben. Und die Objekte müssen das NotifyPropertyChanged-Event feuern, wenn eine dieser Properties changed.

Der frühe Apfel fängt den Wurm.

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Mal kurz als Beispiel:

Das DataGrid enthält die Durchmesser und Mittelpunkte (zu einem gedachten Ursprung und diverses anderes) von Kreisen, ich stelle mir dann diese auf einem Canvas mit Elipsen dar, allerdings brauche ich dafür Durchmesser und absolute Position, die noch skaliert werden müssen.

Bisher erzeuge ich mir eine neue OC, die Margin und X und Y Position enthält. Umrechnung auf Binding sind ja nicht direkt durchführbar, deshalb bin ich den Weg gegangen.

An anderer Stelle benutze ich auch Daten aus einer OC einer ListView und erzeuge daraus einen 2D-Graphen (mittels SciChart) wofür ich auch eine Property passenden Typ (IDataSeries) habe, die an den Graphen gebunden ist. Auch hier wäre eine automatische Aktualisierung wünschenswert, nur kann ich hier definitiv nicht auf die ursprüngliche OC zurückgreifen.

5.299 Beiträge seit 2008
vor 7 Jahren

wie kann eine OC Margin und PosX, PosY enthalten?

Eine OC enthält eine Liste gleichartiger Objekte, also alle Elemente haben den gleichen Datentyp - keinesfalls kann eine OC sowohl Margins als auch Positionen enthalten.

Welchen Datentyp haben die Elemente deiner OC?
Ist das eine Klasse, die du gecodet hast?
Kannst du davon den Code zeigen?

Der frühe Apfel fängt den Wurm.

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Ja klar, ich meine doch eine OC die Objekte enthält.

Jetzt verstehe ich auch, was du vorhin meintest. Leider kann ich die Klasse der Objekte nicht ändern. Diese ist vorgegeben und wird auch so im Model verwendet.

T
461 Beiträge seit 2013
vor 7 Jahren

In meiner ObservableCollection für das DataGrid sind relative Positionen, die ich umrechne und wieder als ObservableCollection für die geometrischen Objekte zur Verfügung stelle.

Kann man sich das jetzt so vorstellen, daß es EINE OC gibt, die an das DG gebunden ist UND zusätzlich für die geom.Objekte?

In der DG werden die Daten umgerechnet und sollten dann auch gleichzeitig die Objekte aktualisieren?

Wenn dem so ist, wie sieht dann ein so ein Item der OC aus?

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Ja, genau.

Die OC für das DataGrid enthält Objekte eine Klasse mit mehreren single für die Durchmesser, Positionen und noch andere physikalische Werte (ebenfalls single). An der kann ich nichts ändern.

Die OC, die ich jetzt für die geometrischen Objekte nutze hat Obejkte einer Klasse mit den Elementen X, Y, (double), Margin (Thickness) und Visibel (Visibility). X, Y und Margin werden aus den Werten der ersten OC berechnet und die Visibel wird gesetzt, je nach dem, ob die weiteren Werte passen.

5.299 Beiträge seit 2008
vor 7 Jahren

Jetzt verstehe ich auch, was du vorhin meintest. Leider kann ich die Klasse der Objekte nicht ändern. Diese ist vorgegeben und wird auch so im Model verwendet. Verstehe ich nicht.
Wenn du das Programm schreibst, dann schreibst du auch die Model-klasse.
Aber egal, wer die Model-Klasse geschrieben hat - imo für eine Model-Klasse höchst ungewöhnlich, dass sie kein PropertyChanged-Event feuern kann.
Zur Not schreibst du halt einen Wrapper, der die fehlende Funktionalität halt dran-patcht.

Wpf funktioniert nicht ohne INotifyPropertyChanged.

Der frühe Apfel fängt den Wurm.

T
461 Beiträge seit 2013
vor 7 Jahren

Wpf funktioniert nicht ohne INotifyPropertyChanged.

Nun ja, funktioniert schon aber total häßlich und umständlich 😉

@NOFX,
Kannst du bitte diese Klasse posten wie die genau aussieht, dann kann man das besser erklären... danke!

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Die Klasse ist als Schnittstelle zwischen mir und einem Entwickler für die Oberfläche definiert worden. Da der aber nicht aus dem Quark kommt, wollte ich eine eigene für Test bauen. Deshalb bin ich jetzt weder der Fachmann für WPF noch ist von meiner Seite besonderer Wert darauf gelegt worden, die optimal für WPF zu gestalten.

Hier mal der wichtige Teil, bereinigt um alle hier unnötigen weiteren Instanzvariablen und Properties.


    public class ABC
    {
        public ABC()
            : base()
        {
        }

        #region Fields

        protected Single _Diameter;
        protected Single _PositionX;
        protected Single _PositionZ;

        #endregion Fields


        #region Properties

        public Single Diameter
        {
            get { return _Diameter; }
            set { _Diameter = value; }
        }

        public Single PositionX
        {
            get { return _PositionX; }
            set { _PositionX = value; }
        }

        public Single PositionZ
        {
            get { return _PositionZ; }
            set { _PositionZ = value; }
        }

        #endregion Properties
    }

Und vielen Dank schon einmal für die Hilfe!

5.299 Beiträge seit 2008
vor 7 Jahren

Jo, damit ist das Problem endlich hofflich korrekt identifiziert: Deine ABC-Klasse implementiert kein INotifyPropertyChanged, und feuert folglich auch kein PropertyChanged-Event, und folglich wird auch kein View geupdated via Databinding.

Wie gesagt: INotifyPropertyChanged ist ganz ganz grundlegend, und das musste iwie nachrüsten.
Konkrete Anleitung hab ich grad nicht auf Pfanne, weil ich verwende immer eine ViewmodelBase-Basisklasse, die INotifyPropertyChanged auf eine schon recht advanced Art implementiert.
Aber müsste sich eiglich googeln lassen.

Der frühe Apfel fängt den Wurm.

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

In der Oberfläche habe ich ja ein DataGrid aufbauend auf einer OC von dieser Klasse. Direkt an die Properties eines Elements der OC (also ein Property dieser Klasse) funktioniert die Datenbindung ja bereits.

Das sieht so aus:

        private ObservableCollection<ABC> _abcList = new ObservableCollection<ABC>();
...
        public ObservableCollection<ABC> AbcList
        {
            get { return _abcList ; }
            set { _abcList = value; }
        }

Daran kann ich direkt den Durchmesser binden:

<Ellipse Width="{Binding AbcList[0].Diameter}" Height="{Binding AbcList[0].Diameter}" Stroke="Black" StrokeThickness="2" HorizontalAlignment="Center" VerticalAlignment="Center""/>

Und der wird auch sofort aktualisiert, wenn ich im DataGrid etwas ändere.

Die Bindung wird aber nicht aktualisiert, wenn ich indirekt über eine zweite Property auf die gleichen Daten zugreife:


public ObservableCollection<abcDXYVis> AbcForView
        {
            get
            {
                ObservableCollection<abcDXYVis> abcForView = new ObservableCollection<abcDXYVis>();
                double scale = 0.225;
                for (int i = 0; i < 10; i++)
                {
                    if ((_abcList != null) && (_abcList.Count > i))
                        abcForView.Add(new abcDXYVis() { Margin = new Thickness(-scale * _abcList[i].PositionX, -scale * _abcList[i].PositionZ, scale * _abcList[i].PositionX,  scale * _abcList[i].PositionZ),
                                      D = scale * _abcList[i].Diameter, Visible = Visibility.Visible });
                    else
                        abcForView.Add(new abcDXYVis() { Visible = Visibility.Hidden });
                }
                return abcForView;
            }
        }
...
    public class abcDXYVis
    {
        public Thickness Margin { get; set; }
        public double D { get; set; }
        public Visibility Visible { get; set; }
    }

XAML:

<Ellipse Width="{Binding abcForView [0].D}" Height="{Binding abcForView [0].D}" Stroke="Black" StrokeThickness="2" HorizontalAlignment="Center" VerticalAlignment="Center""/>

Die Frage ist also, warum klappt das mit der Bindung im ersten Falle überhaupt, wenn ABC nicht von INotifyPropertyChanged abgeleitet ist und wie müsste ich das im zweiten Fall ändern, damit das funktioniert.

5.299 Beiträge seit 2008
vor 7 Jahren

ich kanns nur wiederholen: Deine Abc-Klasse implementiert kein INotifyPropertychanged - das ist das Problem, und das zu korrigieren ist die Lösung.

Dass die Benachrichtigung zwischen den Controls trotzdem funktioniert, ist ein eigenartiges Wpf-Spezial-Feature, von dem ich hab sagen hören, es erzeuge ausserdem Memory-Leaks.
Und wie du gemerkt hast: Auf codeseitige Änderungen kann es nicht reagieren.

Der frühe Apfel fängt den Wurm.

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Dann dürfte aber jetzt doch schon die Bindung des Durchmessers nicht funktionieren. Das geht ja offenbar über die OC, was mich ja auch wundert.

Ich versuche auf jeden Fall die Klasse ABC zu ändern aber eine - wenn auch unschöne - Übergangslösung wäre super.

Kann ich z.B. selber das PropertyChanged Event der OC (AbcList) abfangen und dann wiederum eines für AbcForView auslösen?

5.299 Beiträge seit 2008
vor 7 Jahren

ich muss gestehen, wenn ich mich zum dritten mal wiederholen muss, wird es mir üblicherweise zu blöd.
Wieso machst du nicht einfach mal, was ich dir empfohlen habe? (INotifyPropertyChanged implementieren)

Der frühe Apfel fängt den Wurm.

W
872 Beiträge seit 2005
vor 7 Jahren

Ich benutze gerne PropertyChanged.Fody. Die Doku findest Du unter Github.

Dann brauchst Du nur ein

[ImplementPropertyChanged]

vor die Klasse setzen und jede public Property implementiert dann INotifyPropertyChanged automatisch...

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

ich muss gestehen, wenn ich mich zum dritten mal wiederholen muss, wird es mir üblicherweise zu blöd.
Wieso machst du nicht einfach mal, was ich dir empfohlen habe? (INotifyPropertyChanged implementieren) OK, ich habe das jetzt so implementiert, dass sowohl ABC als auch abcDXYVis INotifyPropertyChanged implementieren. Jetzt habe ich begriffen, dass da kein Weg vorbei führt. 😉

Wie kriege ich jetzt die AbcForView (also die Property im ViewModel die Geometrien berechnet) dazu, ihrerseits die auf die Änderung einzelner Properties eines Elements von AbcList zu reagieren?

Ich benutze gerne
>
. Die Doku findest Du unter
>
.

Dann brauchst Du nur ein

[ImplementPropertyChanged]  

vor die Klasse setzen und jede public Property implementiert dann INotifyPropertyChanged automatisch... Danke für den Tipp, ich gucke mir das mal an!

T
461 Beiträge seit 2013
vor 7 Jahren

Hey,

also bin ich jetzt komplett mischuggi oder ist es offensichtlich 😃 :


     public class abcDXYVis
    {
        public Thickness Margin { get; set; }
        public double D { get; set; }
        public Visibility Visible { get; set; }
    }

Diese Klasse enthält gar kein Property mit dem Namen 'Diameter', da kann ja keine Bindung vorhanden sein...


<Ellipse Width="{Binding abcForView [0].Diameter}" Height="{Binding abcForView [0].Diameter}" Stroke="Black" StrokeThickness="2" HorizontalAlignment="Center" VerticalAlignment="Center""/>

Oder täusch ich mich ?

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Sorry, hatte das beim vereinfachen falsch ersetzt. Muss natürlich .D sein.

T
461 Beiträge seit 2013
vor 7 Jahren

Noch was weiteres:

Du stellst hier immer Blöcke rein, bei denen die wichtigen Teile fehlen...

Ich sehe, daß du jedes Mal innerhalb bei


public ObservableCollection<abcDXYVis> AbcForView

eine neue Instanz erstellst. Wäre mal nicht sooo schlimm.
Das was mir fehlt, ist die Stelle, an der diese 'AbcForView'-Property aktualisiert wird, z.Bsp.:


this.PropertyChanged(this, new PropertyChangedEventArgs("AbcForView"));

Daher es nur ein getter ist, wäre das in diesem Fall unbedingt notwendig, sonst tut sich nie was, weil es eben NICHT die gleiche OC ist vom generischen Typ her UND weil du immer eine neue Instanz erstellst.

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

5.299 Beiträge seit 2008
vor 7 Jahren

Wie kriege ich jetzt die AbcForView (also die Property im ViewModel die Geometrien berechnet) dazu, ihrerseits die auf die Änderung einzelner Properties eines Elements von AbcList zu reagieren? Auf etwas reagieren tut man üblicherweise, indem man das entsprechende Event abonniert.

Ah - du hast ja grad INotifyPropertyChanged implementiert - da täte sich doch anbieten, einfach das PropertyChanged-Event zu abonnieren, um zu reagieren, wenn eine Property sich ändert.
Weil INotifyPropertyChanged .PropertyChanged benachrichtigt (engl: to notify) einen doch, wenn eine Property geändert wurde.

Der frühe Apfel fängt den Wurm.

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Auf etwas reagieren tut man üblicherweise, indem man das entsprechende Event abonniert.

Ah - du hast ja grad INotifyPropertyChanged implementiert - da täte sich doch anbieten, einfach das PropertyChanged-Event zu abonnieren, um zu reagieren, wenn eine Property sich ändert.
Weil INotifyPropertyChanged .PropertyChanged benachrichtigt (engl: to notify) einen doch, wenn eine Property geändert wurde.
👍

Ich habe jetzt in jeder neuen Instanz von ABC, die ich der _abcList hinzufüge, direkt das Event abonniert. Im EventHandler löse ich dann nach Überprüfung, ob das Objekt aus der passenden Klasse (ABC) stammt, auch wieder das Event aus, dass sich AbcForView geändert hat.

        private void ABCViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)  
        {  
            if (sender.GetType() == typeof(ABC))  
                RaisePropertyChangedEvent("AbcForView");  
        }  

Geht das noch eleganter, als für jede Instanz den Handler einzeln zuzuweisen?

Ich sehe, daß du jedes Mal innerhalb bei eine neue Instanz erstellst. Wäre mal nicht sooo schlimm.
Das was mir fehlt, ist die Stelle, an der diese 'AbcForView'-Property aktualisiert wird, z.Bsp.:

  
this.PropertyChanged(this, new PropertyChangedEventArgs("AbcForView"));  
  

Daher es nur ein getter ist, wäre das in diesem Fall unbedingt notwendig, sonst tut sich nie was, weil es eben NICHT die gleiche OC ist vom generischen Typ her UND weil du immer eine neue Instanz erstellst.
Das werde ich auch noch eleganter lösen und nicht jedes Mal eine komplett neue OC erstellen. Da ich ja im Eventhandler (s.o.) weiß, dass jetzt AbcForView neu erstellt werden muss.

T
461 Beiträge seit 2013
vor 7 Jahren

Hey,

ähhm anscheinend hab ich irgendwas verpasst, warum du selbst das Event abonnierts, normaler weise mußt du das Event aufrufen...

(Und der Namen vom Property ist ja im PropertyChangedEventArgs enthalten...)

Edit1:
Ok, weiß jetzt nicht genau wie du das alles anstellst aber eine einfachere Methode wäre:


if(sender == null) return;
RaisePropertyChangedEvent(sender.GetType().Name);

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Ich abonniere ja das Event der Elemente der einen OC (_abcList / AbcList) um manuell das Event der anderen (AbcForView) auszulösen.

Wenn ich das Event im Get (von AbcForView) auslösen würde, würde das ja eine Endlosschleife werden, weil das Event (im Get) alle Elemente der View (die an AbcForView gebunden sind) anstiften würde wieder das Get (von AbcForView) aufzurufen.

5.299 Beiträge seit 2008
vor 7 Jahren

Aber warum willst du manuell das Event der anderen (AbcForView) auslösen?
Das ist sehr ungewöhnlich - Normal braucht man das nicht.

Der frühe Apfel fängt den Wurm.

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Jetzt brauche ich das auch nicht mehr manuell auszulösen. Ich starte im Eventhandler die Neuberechnung und durch die Zuweisung wird das im Setter dann ja automatisch erledigt. So spare ich mir auch das ständige Erzeugen einer neuen OC.

Eventhandler:

        private void ABCViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (sender.GetType() == typeof(ABC))
                AbcForView = CalculateAbcForView();
        }

Porperty:

        public ObservableCollection<abcDXYVis> AbcForView
        {
            get { return _AbcForView; }
            set { _AbcForView = value; RaisePropertyChangedEvent("AbcForView"); }
        }

Interne Variable:

private ObservableCollection<abcDXYVis> _AbcForView = new ObservableCollection<abcDXYVis>();

Und die Berechnung:

        public ObservableCollection<abcDXYVis> CalculateAbcForView()
        {
            ObservableCollection<abcDXYVis> abcForView = new ObservableCollection<abcDXYVis>();
            double scale = 0.225;
            for (int i = 0; i < 10; i++)
            {
                if ((_abcList != null) && (_abcList.Count > i))
                    abcForView.Add(new abcDXYVis() { Margin = new Thickness(-scale * _abcList[i].PositionX, -scale * _abcList[i].PositionZ, scale * _abcList[i].PositionX,  scale * _abcList[i].PositionZ),
                                      D = scale * _abcList[i].Diameter, Visible = Visibility.Visible });
                else
                    abcForView.Add(new abcDXYVis() { Visible = Visibility.Hidden });
            }
            return abcForView;
        }
T
461 Beiträge seit 2013
vor 7 Jahren

Wenn ich das Event im Get (von AbcForView) auslösen würde, würde das ja eine Endlosschleife werden, weil das Event (im Get) alle Elemente der View (die an AbcForView gebunden sind) anstiften würde wieder das Get (von AbcForView) aufzurufen.

Hmm, warum machst du kein dummy Set dazu?

Ein "_AbcForView" Feld hinzufügen, im getter dieses zurückschicken und im setter die ganze Erstellung mit dem RaiseEvent...

Somit müßtest du beim set "AbcForView = null;" aufrufen und der Rest erledigt sich von selbst, obwohl das jetzt nicht Standard ist und auch nicht hübsch, nur in der aktuellen Lage...

Besser wäre in beiden Klassen ein ID Feld hinzufügen, bei dem man die 2 Klassen immer zusammenfinden und ohne ständig neue Instanzen zu erstellen, dann einfach die Properties der anderen Klasse berechnend zu ändern.

Somit würde sich das mit den Bindungsproblem auch lösen lassen...

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

N
NOFX Themenstarter:in
42 Beiträge seit 2015
vor 7 Jahren

Ich habe ja jetzt alles eigentlich sauber mit Get und Set und ohne manuelle PropertyChange-Events.

Einzig das neu Erzeugen der OC in CalculateAbcForView ist vielleicht nicht das schönste. Das könnte ich über die von dir vorgeschlagenen IDs noch ändern, sodass ich in der AbcForView nur das passende Element ändern muss. Dafür muss ich aber die ABC-Klasse schon wieder anpassen, was ich eher vermeiden möchte.

T
461 Beiträge seit 2013
vor 7 Jahren

Dafür muss ich aber die ABC-Klasse schon wieder anpassen, was ich eher vermeiden möchte.

Sowas nennt man Lernprozess, kennt glaub ich ein jeder 😉
Ich könnte ein liedchen davon singen...
Einfach nach einer ordentlichen Pause (hilft immer ungemein) das Ganze angehen und es ist ja nicht so viel arbeit mit der ID...könnte sogar noch für weitere nützliche Dinge gut sein, die jetzt noch gar nicht bedacht waren.

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄