Laden...

Silverlight - UI Objekte über Server Callback animieren

Erstellt von Pico1184 vor 11 Jahren Letzter Beitrag vor 11 Jahren 1.424 Views
Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 11 Jahren
Silverlight - UI Objekte über Server Callback animieren

Hallo zusammen,

ich muss etwas ausholen um mein Problem zu schildern.

Ich entwickle nun seit über 1,5 Jahren ein Visualisierungssystem für Industrieanlagen.
Dieses System arbeitete in der Vergangenheit folgendermaßen:

Über eine WPF Öberfläche können Daten (Variablen aus SPS Steuerungen etc.) in einer SQL Datenbank verwaltet werden.

Ein WCF Dienst übernimmt die Kommunikation mit der Steuerung der Industrieanlage und frägt die vorher projektierten Variablen (Datenbank) nach ihren aktuellen Werten ab.

Ein HttpLongPoll Server veröffentlich diese Daten nach dem Publisher/Subscriber Modell an die Clients (Webseite).

Bisher waren die Clients reine Html Seiten welche über JavaScript (jQuery) Daten des Server konsumiert haben.

Nun möchte ich auf Silverlight umstellen.

Mein Problem ist hierbei nur die Oberfläche und das ViewModel so zu gestalten, dass das Model unabhängig von der Oberfläche bleibt.

Die View kann immer verschiedene Objekte enthalten. Diese Objekte sollen je nach Wert aus der Anlagensteuerung farbig animiert werden.

Dazu registriere ich die interessanten Variablen am HttpLongPoll Server und bekomme falls diese sich ändern über einen Callback aktuelle Werte zurück!


//Signale registrieren (Variablenname, zu animierendes Objekt (z.B Rectangle), callback methode
 _actionHandler.AddSignalActionHandler("SPS1_01_01", "Test1", ObjectColoring);
 _actionHandler.AddSignalActionHandler("SPS1_01_02", "Test2", ObjectColoring);
 _actionHandler.AddSignalActionHandler("SPS1_01_03", "Test3", ObjectColoring);  
 _actionHandler.RegisterSession(OnErrorEx);


//Callback
private void ObjectColoring(string signalName, int signalValue, string objectId)
{
            this.Dispatcher.BeginInvoke(() => AddLine(signalName + ": " + signalValue + " " + objectId));


            if (signalValue == 0)
            {
                Dispatcher.BeginInvoke(() =>
                {
//die UI Elementanimation muss dynamisch erfolgen
                    ellipse1.Fill = new SolidColorBrush(Colors.Gray);
                    rectangle1.Fill = new SolidColorBrush(Colors.Gray);
                    textBox1.Background = new SolidColorBrush(Colors.Gray);
                });
                return;
            }
            if((signalValue & 0x100) > 0)
            {
//die UI Elementanimation muss dynamisch erfolgen
                Dispatcher.BeginInvoke(() =>
                                           {
                                               ellipse1.Fill = new SolidColorBrush(Colors.Green);
                                               rectangle1.Fill = new SolidColorBrush(Colors.Green);
                                               textBox1.Background = new SolidColorBrush(Colors.Green);
                                           });                        
            }
          
        }

Über die Callback Methode "ObjectColoring" bekomme ich alle aktuellen Daten und den Objektnamen (objectId) des UI Elementes zurück.

Nun möchte ich dies aber dynamisch haben => also nicht statisch über
ellipse1.Fill = new SolidColorBrush(Colors.Gray);

sondern gültig für alle Objekte auf der UI.

Wie kann ich vom String objectId auf meine Controls zugreifen?
Ich kann mit dieser Lösung auch nicht vermeiden, dass mein ViewModel die UI Objekte kennen muss.

Vielleicht hat von euch jemand noch einen anderen Lösungsansatz....

Hoffe ich habe mich einigermaßen verständlich ausgedrückt. Gar nicht sooo leicht zu erklären....

Grüße Pico

S
74 Beiträge seit 2005
vor 11 Jahren

Hallo Pico,
etwas Offtopic:
Warum um Gottes Willen willst du jetzt auf Silverlight umstellen?
Stell lieber auf HTML Canvas um, das habe ich mit unserem SCADA (wird nur in Kundenprojekten verwendet) bereits hinter uns. Oder was spricht dagegen?

Hinweis von gfoidl vor 11 Jahren

Vorsorglich der Hinweis dass hier nicht über die Zukunft von Silverlight diskutiert werden soll. Dazu haben wir separate Threads.

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 11 Jahren

Ich denke nicht das Silverlight tot ist...aber wie gfoidl schon schrieb das ist ein anderes Thema und hat mit meiner Fragestellung nicht direkt was zu tun!

Ich habe diverse Gründe warum ich vorerst noch Silverlight nutzen möchte!

Und deswegen hoffe ich auch dass mir trotzdem noch jemand Tipps zu meinem Problem geben kann 😉

Grüße Pico

J
641 Beiträge seit 2007
vor 11 Jahren

Also Ich kann dir jetzt nicht direkt zu deinem Problem was schreiben, aber Ich kann dir schreiben wie Ich im groben unser Visualisierungsystem aufgebaut habe.

Bei mir gibt es auf den Server und im Client Klassen des Typs Tag (Sind verschiedene aber ein Tag repräsentiert einen SpsWert). In der Silverlight oberfläche sind z.B. textbox.Text oder Backcolor eines elements an ein Tag objekt gebunden. Dadurch stelle ich beim öffnen eines bildes fest welcher tag vom server gelesen werden soll (tag implementiert inotifypropertychanged, und beim anfügen an das event wird dem server gesagt, das diese variable nun in die leseliste soll.)

Der Server liest nun die tags von der sps (immer zyklisch). Wenn sich ein Tag ändert, wird das in eine sendeliste an den client eingetragen, welche alle 50ms per callback an die clients (wpf und silverlight geschickt wird). Im client wird der wert nun dem tag objekt zugewiesen, und da die felder und farben gebunden sind werden diese aktualisiert!

cSharp Projekte : https://github.com/jogibear9988

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 11 Jahren

ich bekomme die Daten von Server in diesem Format


private void ObjectColoring(string signalName, int signalValue, string objectId)

Also hier die ObjectId bzw. den Objektnamen meines Silverlight Objektes.
Anhand diesem string müsste ich dann auf das UI Objekt zugreifen können.......

Könnte auch die Callback Signatur ändern und zum Beispiel das ganze UI Object übergeben:


_actionHandler.AddSignalActionHandler("SPS1_01_01", ellipse1, ObjectColoring);

Nur das Problem ist das ich ja verschiedene UI Elemente habe also nicht nur ellipsen.

Wie kann ich dann auf diese Elemente über die Callback Methode zugreifen?


private void ObjectColoring(string signalName, int signalValue, Ellipse ellipse)

Grüße Pico

J
641 Beiträge seit 2007
vor 11 Jahren

Warum machst du dir auf dem Client nicht ein Objekt welches den Wert repräsentiert (bei mir ist das das Tag Objekt). Dieses Implementiert INotifyPropertyChanged, und du Bindest die Propertys welche sich bei bei Änderung ändern sollen, an eine Property des Tag Objekts?

cSharp Projekte : https://github.com/jogibear9988

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 11 Jahren

Warum machst du dir auf dem Client nicht ein Objekt welches den Wert repräsentiert (bei mir ist das das Tag Objekt). Dieses Implementiert INotifyPropertyChanged, und du Bindest die Propertys welche sich bei bei Änderung ändern sollen, an eine Property des Tag Objekts?

Mir gefällt nicht, dass ich für jede SPS Variable eine Property brauche welche dann an mein UI Object gebunden ist. In diesem Fall müsste ich ja für jede Variable händisch eine Property anlegen.

Wir haben ja bisher HTML und jquery verwendet, dort hatte ich eine Javascript Funktion die vom Server aufgerufen wurde und über diese eine Funktion habe ich alle UI Elemente animiert, dies hat natürlich eine enorme zeitersparnis und quellcodeeinparung zur Folge.

Dies müsste doch auch mit Silverlight funktionieren?!?!?

Grüße Pico

J
641 Beiträge seit 2007
vor 11 Jahren

klar geht das, du kannst ja eine duplex verbindung aufbauen.
ich erzeug mit halt mein objekt mit propertys für jeden tag dynamisch. sogar mit unterpropertys. da kannst du dann z.b. so binden: {binding tagclient.tags.rbg.speed} wobei das objekt tags zur laufzeit erstellt wird!

cSharp Projekte : https://github.com/jogibear9988

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 11 Jahren

Kannst du mir mal ein Codebeispiel zeigen? Kann es mir noch nicht so richtig vorstellen wie du das genau machst!

Grüße Pico

J
641 Beiträge seit 2007
vor 11 Jahren

Ok, dann beschreib Ich mal mein Vorgehen:

In meinem Xaml lege Ich mir im Datacontext ein Objekt an, welches Zugriff auf meinen Visu Server hat:


 <UserControl.DataContext>
        <visu:VisuClientStaticFix />
    </UserControl.DataContext>

dann kann Ich z.B. in einem TextBlock den Text so an eine Server Varible Binden:


<TextBlock Text="{Binding Instance.TagClient.Tags.server.TestBB.Value}" />

das gute an der Sache ist nun, das Objekt TagClient.Tags hat gar nciht die Property "server" oder der "server" die Property TestBB. Die sind alle vom Typ TagFolder, welcher ein DynamicObject ist, und somit die Propertys zur Laufzeit erzeugt werden. (Damit Databinding funktiniert, implementiert der Typ auch noch INotifypropertyChanged (und unter Silverligt noch ICustomTypeProvider, unter WPF geht das Binding auch schon so!).

Nun kommt an den Client per ServerCallback eine Liste von geänderten werden:


public class TagValueWrapperDTO 
    {
        public string Name { get; set; }
        public object Value { get; set; }
        public TagValueQuality TagValueQuality { get; set; }      
    }   

der durchsucht seine Liste von Tag Objekten, weist diesen die neuen Werte zu.

Hoffe so kann man meinen Ansatz einigermaßen verstehen.

cSharp Projekte : https://github.com/jogibear9988