Я пытаюсь определить, правильно ли я делаю это. Вот поток данных, который я имел настройки с MVVM в приложении UWP:
view viewmodel модель signalrclient signalrserver Другие вещи
Я написал клиент SignalR, который передается конструктору модели при инициализации. Каждый экземпляр модели устройства имеет клиент SignalR, который позволяет серверу SignalR вызовать методы на всех подключенных устройствах. Вот проблема: < /p>
Когда сервер SignalR вызывает метод на устройстве, он делает это с зарегистрированным обратным вызовом в модели. Нет проблем, этот обратный вызов устанавливает свойство, а модель наследует от ObservableObject от communitytoolkit.mvvm.componentmodel , чтобы он мог обновить ViewModel и так далее, пока пользовательский интерфейс не покажет изменение.
Теперь нам нужно пойти в другую сторону. Просмотр обновляется, ViewModel также наследуется от ObservableObject , свойство ViewModel изменяется по просмотру из -за двухстороннего x: bind На элементе модель обновляется ViewModel, установив свойство модели общего аудидиовума. Он получает обновленное значение и может затем вызвать правильный метод Invoke в экземпляре клиента SignalR, чтобы вызвать удаленный метод на сервере. События, выпускающие оба направления? Использование только событий PropertyChanged в ViewModel для обновления модели так же, как многие статьи и стека* Q & A Предлагают, что это не достаточно.
Просмотр содержит: < /p>
< /code>
-код, содержит: < /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 содержит: < /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>
Модель содержит: < /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>
Это отлично подходит для получения изменений модели от сети в представление. Мне нужно получить изменения в представлении обратно на устройство и по сети. Если я вызовут метод InvokeAsync на сигнале, который мне нужен в ViewModel, или в «сеттере» свойства модели, он будет вызван в любое время, когда том обновляется из сети. Это цикл обратной связи, о котором я говорил. Полем Это в основном ситуация общего состояния. , Я могу выполнить метод сервера SignalR, необходимый для его изменения на самом устройстве, и при этом обновлять представление в любое время, когда службы сетевой интеграции также обновляют его. Даже попытаться это не обновлять свойство AudioVolume в обратном вызове NetDevice SignalRClient и вместо этого обновить только частную переменную поддержки, а затем вручную поднять событие, измененное свойство в этом обратном вызове, чтобы ViewModel мог получить доступ к Getter для этого свойства и PropeGate это в представление с помощью привязки данных TwoWay. .Invokeasync Метод обновления фактического аппаратного устройства. Это хороший способ решить эту проблему? Потому что, когда я делаю это таким образом, и как показывают комментарии выше, это идет плохо. < /P>
Вот фотография фактического виджета. И да, когда я внедряю вышеуказанную стратегию, а обновления появляются из сети, без проблем. Когда используется слайдер, он сходит с ума, и до тех пор, пока приложение работает, он подпрыгивает повсюду между первоначальным значением и значением назначения, как происходит обратная связь «шторм», описанная выше. Я был чертовски осторожен и до сих пор не могу понять это поведение. По сути, я пытаюсь установить привязку к двум плаванию между слоем интеграции сети системной архитектуры. i.sstatic.net/51uquyph.png "/>
Подробнее здесь: https://stackoverflow.com/questions/794 ... ntegration
XAML и MVVM в приложении UWP с интеграцией SignalR ⇐ C#
Место общения программистов C#
-
Anonymous
1739338223
Anonymous
Я пытаюсь определить, правильно ли я делаю это. Вот поток данных, который я имел настройки с MVVM в приложении UWP:
view viewmodel модель signalrclient signalrserver Другие вещи
Я написал клиент SignalR, который передается конструктору модели при инициализации. Каждый экземпляр модели устройства имеет клиент SignalR, который позволяет серверу SignalR вызовать методы на всех подключенных устройствах. Вот проблема: < /p>
Когда сервер SignalR вызывает метод на устройстве, он делает это с зарегистрированным обратным вызовом в модели. Нет проблем, этот обратный вызов устанавливает свойство, а модель наследует от ObservableObject от communitytoolkit.mvvm.componentmodel , чтобы он мог обновить ViewModel и так далее, пока пользовательский интерфейс не покажет изменение.
Теперь нам нужно пойти в другую сторону. Просмотр обновляется, ViewModel также наследуется от ObservableObject , свойство ViewModel изменяется по просмотру из -за двухстороннего x: bind На элементе модель обновляется ViewModel, установив свойство модели общего аудидиовума. Он получает обновленное значение и может затем вызвать правильный метод Invoke в экземпляре клиента SignalR, чтобы вызвать удаленный метод на сервере. События, выпускающие оба направления? Использование только событий PropertyChanged в ViewModel для обновления модели так же, как многие статьи и стека* Q & A Предлагают, что это не достаточно.
Просмотр содержит: < /p>
< /code>
-код, содержит: < /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 содержит: < /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>
Модель содержит: < /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>
Это отлично подходит для получения изменений модели от сети в представление. Мне нужно получить изменения в представлении обратно на устройство и по сети. Если я вызовут метод InvokeAsync на сигнале, который мне нужен в ViewModel, или в «сеттере» свойства модели, он будет вызван в любое время, когда том обновляется из сети. Это цикл обратной связи, о котором я говорил. Полем Это в основном ситуация общего состояния. , Я могу выполнить метод сервера SignalR, необходимый для его изменения на самом устройстве, и при этом обновлять представление в любое время, когда службы сетевой интеграции также обновляют его. Даже попытаться это не обновлять свойство AudioVolume в обратном вызове NetDevice SignalRClient и вместо этого обновить только частную переменную поддержки, а затем вручную поднять событие, измененное свойство в этом обратном вызове, чтобы ViewModel мог получить доступ к Getter для этого свойства и PropeGate это в представление с помощью привязки данных TwoWay. .Invokeasync Метод обновления фактического аппаратного устройства. Это хороший способ решить эту проблему? Потому что, когда я делаю это таким образом, и как показывают комментарии выше, это идет плохо. < /P>
Вот фотография фактического виджета. И да, когда я внедряю вышеуказанную стратегию, а обновления появляются из сети, без проблем. Когда используется слайдер, он сходит с ума, и до тех пор, пока приложение работает, он подпрыгивает повсюду между первоначальным значением и значением назначения, как происходит обратная связь «шторм», описанная выше. Я был чертовски осторожен и до сих пор не могу понять это поведение. По сути, я пытаюсь установить привязку к двум плаванию между слоем интеграции сети системной архитектуры. i.sstatic.net/51uquyph.png "/>
Подробнее здесь: [url]https://stackoverflow.com/questions/79429060/xaml-and-mvvm-in-uwp-application-with-signalr-integration[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия