XAML und MVVM in der UWP -Anwendung mit SignalR -IntegrationC#

Ein Treffpunkt für C#-Programmierer
Guest
 XAML und MVVM in der UWP -Anwendung mit SignalR -Integration

Post by Guest »

Ich versuche festzustellen, ob ich das richtig mache. Hier ist der Datenfluss, den ich mit MVVM in einer UWP -App eingerichtet habe:
Ansicht ViewModel Modell SignalRclient SignalRServer Andere Dinge
Ich habe einen SignalR -Client geschrieben, der bei der Initialisierung an den Modellkonstruktor übergeben wird. Jede Modellinstanz eines Geräts verfügt über einen SignalR -Client, mit dem der SignalR -Server Methoden auf allen verbundenen Geräten aufruft. Hier ist das Problem: < /p>
Wenn der SignalR -Server eine Methode auf einem Gerät aufruft, wird dies mit einem registrierten Rückruf im Modell geschieht. Kein Problem, dass Callback eine Eigenschaft festlegt und das Modell von ObservableObject von CommunityToolkit.mvvm.comPonentModel erbragt /> Jetzt müssen wir in die andere Richtung gehen. Die Ansicht wird aktualisiert, ViewModel erbt auch von ObservableObject , ViewModel -Eigenschaft wird durch Ansicht durch Ansicht geändert. Es erhält den aktualisierten Wert und kann dann die richtige Aufrufmethode in der SignalR -Client -Instanz aufrufen, um die Remote -Methode auf dem Server aufzurufen. Ereignisse, die beide Richtungen abfeuern? Verwenden Sie nur PropertyChanged -Ereignisse im ViewModel, um das Modell so viele Artikel und Stapel zu aktualisieren.
Die Ansicht enthält: < /p>

< /code>
Code-Behind enthält: < /p>
using Microsoft.Extensions.DependencyInjection;
using MyProj.ViewModels;
using Windows.UI.Xaml.Controls;

namespace MyProj.Views
{
public sealed partial class ScenarioEnvConfig : UserControl
{
private readonly ScenarioEnvConfigVm _vm;

public ScenarioEnvConfig()
{
this.InitializeComponent();
_vm = (ScenarioEnvConfigVm)App.Current.Services.GetRequiredService(typeof(ScenarioEnvConfigVm));
}
}
}
< /code>
ViewModel enthält: < /p>
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.ComponentModel;
using MyProj.Models;
using MyProj.Services;
using Windows.UI.Core;

namespace MyProj.ViewModels
{
public class ScenarioEnvConfigVm : ObservableObject
{
private NetDevice _netDevice;

private int _audioVolume;
public int AudioVolume
{
get => _audioVolume;
set
{
SetProperty(ref _audioVolume, value);
// This next statement will propegate view changes
// to the model.
// If I try to update SignalRServer here, it gets
// called when updates come from network or view
// causing server to receive and propagate to all
// clients, unnecessary update, which they will all
// do again, in turn, creating the storm.
if (_netDevice != null)
_netDevice.AudioVolume = value;
}
}

public ScenarioEnvConfigVm(NetDevice netDev)
{
_netDevice = netDev;
_netDevice.PropertyChanged += new
PropertyChangedEventHandler(OnNetDevPropertyChanged);
}

private async void OnNetDevPropertyChanged(object sender,
PropertyChangedEventArgs e)
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (e.PropertyName == "AudioVolume")
AudioVolume = _netDevice.AudioVolume;
});
}

}
}
< /code>
Das Modell enthält: < /p>
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;
using MyProj.OpenAPIs;
using MyProj.Services;

namespace MyProj.Models
{
public class NetDevice : ObservableObject
{
private readonly SignalRClient _srClient;

private int _audioVolume = 0;
public int AudioVolume
{
get => _audioVolume;
// If I try to update SignalRServer here, it gets
// called when updates come from network or view.
set => SetProperty(ref _audioVolume, value);
}

public NetDevice(SignalRClient srClient)
{
_srClient = srClient;
_srClient.OnVolumeChanged += OnAudioVolumeChanged;
_ = _srClient.ConnectAsync();
}

private void OnAudioVolumeChanged(int volume)
{
AudioVolume = volume;
// I am thinking this should look more like:
// _audioVolume = volume;
// PropertyChanged?.Invoke(volume);
// With this change, I *should* be able to freely
// make the network call in the setter above
// and trust that it came from the view/viewmodel.
// and know that signalr server will not get another
// update request from a client it just updated.
// However, the slider goes crazy when I do this.
// Is this a cancellation token problem? Do I need
// to cancel update operations that are in-flight
// as two-way slider events are being processed so
// that prior update operations can be cancelled
// until a final value is settled upon?
}
}
}
< /code>
Dies eignet sich hervorragend für das Abrufen von Modelländerungen vom Netzwerk zur Ansicht. Ich muss Änderungen in der Ansicht zurück zum Gerät und über das Netzwerk abrufen. Wenn ich einen Anruf bei der Invokeasync -Methode auf den SignalRclient einsetzt, das ich entweder im ViewModel oder in der "Setter" der Modelleigenschaft benötige, wird dies bei jedem Volumen aufgerufen, wenn das Volumen aus dem Netzwerk aktualisiert wird. Dies ist die Rückkopplungsschleife, über die ich gesprochen habe. . Es handelt sich im Grunde genommen um eine gemeinsame Zustandssituation. Ich kann die SignalR Server -Methode ausführen, die erforderlich ist, um sie auf dem Gerät selbst zu ändern Um dies überhaupt zu versuchen, bedeutet dies, die Eigenschaft audiovolume im NetDevice Model SignalRclient Callback nicht zu aktualisieren und stattdessen nur die private Backing -Variable zu aktualisieren und dann das Ereignis in diesem Rückruf manuell zu erhöhen, sodass das ViewModel auf den Getter für diese Eigenschaft und das Propegate zugreifen kann Es ist die Ansicht über die Twoway -Datenbindung. .Invokeasync -Methode, um das tatsächliche Hardware -Gerät zu aktualisieren. Ist das ein guter Weg, um dieses Problem zu lösen? Denn wenn ich es so mache und wie die obigen Kommentare zeigen, geht es schlecht. < /P>
Hier ist ein Foto des eigentlichen Widgets. Und ja, wenn ich die obige Strategie implementieren und Updates aus dem Netzwerk eingehen, kein Problem. Wenn der Schieberegler verwendet wird, wird er verrückt und solange die App läuft, wird überall zwischen seinem ursprünglichen Wert und dem Zielwert der oben beschriebenen Feedback "Sturm" stattfindet. Ich war höllisch vorsichtig und kann das immer noch nicht gut verhalten. Ich versuche im Wesentlichen, eine Twoway -Bindung zwischen dem Slider -Widget und der Systemarchitektur -Netzwerkintegrationsschicht herzustellen. I.Sstatic.net/51uquyph.png "/>

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post