Laden...

MVVM Kommunikation mit anderen Klassen

Erstellt von MatEleven vor 2 Jahren Letzter Beitrag vor 2 Jahren 337 Views
M
MatEleven Themenstarter:in
2 Beiträge seit 2022
vor 2 Jahren
MVVM Kommunikation mit anderen Klassen

Hallo Forum,

mit folgendem Code versuche ich Daten in ein View zu bekommen, die sich in einer Methode einer Klasse (MyClass) außerhalb der aufrufenden Klasse (ViewModel) befinden. Bei Aufruf der Methode innerhalb ViewModel funktioniert der Code, außerhalb nicht. Auch wenn ich ein Object im Konstruktor erstelle geht es nicht. Wie ist die richtige Vorgehensweise?


namespace WpfApp8
{
    class ViewModel : INotifyPropertyChanged
    {
                       
        public MyCommand ActionCommand
        {
            get;
            private set;
        }
        
        public ViewModel()
        {
            ActionCommand = new MyCommand()
            {
                CanExecuteFunc = obj => true,
                //ExecuteFunc = MyActionFunc,
               ExecuteFunc = MyClass.MyActionFunc                 
            };            

        }      

        public event PropertyChangedEventHandler PropertyChanged;
        
        private string myname; 
        public string MyName
        {
            get => myname;
            set  {
                    myname = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyName)));                  
               }
        }

        public void MyActionFunc(object param)
        {
            MyName = "Fred";
        }

    }

    public class MyClass
    {
        public static void MyActionFunc(object param)
        {
            string MyName = "Peter";        
        }
    }
}

Und das Binding im View,


<TextBox Name="textBox1" Grid.Column="2"  Grid.Row="2" Text="{Binding MyName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
           

VG Matthias

4.938 Beiträge seit 2008
vor 2 Jahren

Hallo und willkommen,

deine Code innerhalb von MyClass.MyActionFunc


string MyName = "Peter";

bewirkt gar nichts, da du damit eine lokale Variable erstellst (die nichts mit der MyName-Eigenschaft im ViewModel zu tun hat).

Warum willst du das denn auslagern?
Du könntest aber einfach den Text zurückgeben lassen:


MyName = MyClass.GetName();


public class MyClass
{
    public static string GetName()
    {
        return "Peter";
    }
}

Außerdem erstelle am besten für die INotifyPropertyChanged-Funktionalität eine Basisklasse (häufig BaseViewModel oder ViewModelBase genannt).
Es gibt das CallerMemberNameAttribute, um den Aufruf zu vereinfachen: How To Use CallerMemberName Attribute In WPF With MVVM Pattern.

PS: Falsches Subforum -> WPF

M
MatEleven Themenstarter:in
2 Beiträge seit 2022
vor 2 Jahren

Hallo Th69,

vielen Dank für Deine Überlegung. Der Code macht natürlich nichts, weil ich noch keine Funktionalität zwischen den Klassen habe. Ich habe einiges rumprobiert mit Objekten und Settern etc.
Im konkreten Fall befindet sich in der Klasse ein Thread, daher ist eine Rückgabe mit

return

unpraktisch, weil der Task beendet würde. Außerdem steht die Variable

Name

nur beispielhaft für die übertragenden kontinuierlich erzeugten Daten aus dem Thread.
Ich denke in Richtung Interface, weiss aber nicht genau wie ich die Verbindung dann schaffe.


 public class MyClass
    {
        public string MyName;     
        public static async Task MyActionFunc(object param)
        {
            string MyName = "Peter";  
            ...
            var task = Task.Run(() => { ... });
            ...
            
            await task;      
        }
    }

VG Matthias

PS: Soweit ich we iss gibt es in Net Core 5 kein Member ViewModelBase. Benutze daher ObservableObject.

16.830 Beiträge seit 2008
vor 2 Jahren

Das ist ein Task, kein Thread. Tasks sind aber der richtige Weg.
Hast Du kontinuierlich Aktualisierungen, dann macht oft ein Message Pattern sinn, zB via Reactive Extensions.
https://github.com/dotnet/reactive

Daten werden in eine Subscription gepumpt, und das ViewModel reagiert auf Subscription Events, um Daten anzuzeigen (binden).
Erleichtert auch das asynchrone Handling enorm.

4.938 Beiträge seit 2008
vor 2 Jahren

Wenn du aus einem Thread (bzw. Task) Daten an den UI-Thread senden willst, dann s. [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke).

Und am besten dann mittels eines eigenen Ereignisses (mit entsprechend eigener von EventArgs abgeleiteter Klasse): [FAQ] Eigenen Event definieren / Information zu Events (Ereignis/Ereignisse)

Es ginge zwar auch mit einem Interface (auch hier mittels Dispatcher.Invoke), aber die Kopplung ist dann enger als bei einem Ereignis.

PS: Ich halte await Task.Run() eher für ein Anti-Pattern (s. z.B. Avoiding simple mistakes in async await).