为了账号安全,请及时绑定邮箱和手机立即绑定

如何从 ViewModel 异步更新 UI 元素

如何从 ViewModel 异步更新 UI 元素

C#
慕盖茨4494581 2023-08-20 10:10:14
我在多个表单上使用标签来显示从 WCF 服务调用的天气数据。我希望每分钟进行一次更新,以显示更新的天气数据,而不干扰用户交互。我收到以下错误:“必须在与 DependencyObject 相同的线程上创建 DependencySource。”我有一个用于异步获取天气数据的视图模型,它继承自 ViewModelBase 来处理属性更改事件。ViewModel 中的属性绑定到标签天气视图模型public class WeatherDataVM : ViewModelBase{    private string _windString;    private SolidColorBrush _windState;    private DispatcherTimer _timer;    public WeatherDataVM()    {        _timer = new DispatcherTimer(DispatcherPriority.Render);        _timer.Interval = TimeSpan.FromSeconds(10);        _timer.Tick += async (sender, args) => {await Task.Run(() => GetWindAsync()); };        //_timer.Tick += _timer_Tick;        _timer.Start();        GetWind();    }    private void GetWind()    {        var weatherFromService = Services.Instance.EmptyStackService.GetWeather();        var windSpeed = Convert.ToDouble(weatherFromService.Windspeed);        var maxGust = Convert.ToDouble(weatherFromService.Max_Gust_In_Last_Min);        var windSpeedMPH = Math.Round(windSpeed * 1.15078, 1);        var maxGustMPH = Math.Round(maxGust * 1.15078, 1);        var windString = $"W/S: {windSpeedMPH}({maxGustMPH})";        var windState = new Color();        if (windSpeed >= 40)            windState = Color.FromRgb(255, 64, 64);        else if (windSpeed >= 24)            windState = Color.FromRgb(255, 212, 128);        else            windState = Color.FromRgb(0, 255, 0);        _windState = new SolidColorBrush(windState);        _windString = windString;    }    private async Task GetWindAsync()    {        var weatherFromService = Services.Instance.EmptyStackService.GetWeather();        var windSpeed = Convert.ToDouble(weatherFromService.Windspeed);        var maxGust = Convert.ToDouble(weatherFromService.Max_Gust_In_Last_Min);        var windSpeedMPH = Math.Round(windSpeed * 1.15078, 1);        var maxGustMPH = Math.Round(maxGust * 1.15078, 1);        var windString = $"W/S: {windSpeedMPH}({maxGustMPH})";    }
查看完整描述

1 回答

?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

如果冻结后台线程,则可以在后台线程上创建画笔:

var brush = new SolidColorBrush(windState);
brush.Freeze();
WindState = brush;

DispatcherTimer但如果只是Task.Run在事件处理程序中调用,则使用 a 没有多大意义Tick

假设您的事件处理程序仅创建画笔并且不直接操作任何 UI 元素(当然不应该这样做,因为它是在视图模型中实现的),您可以使用System.Timer.Timer。它的Elapsed事件在线程池线程上排队等待执行,您可以在其中查询服务而不会阻塞 UI。


查看完整回答
反对 回复 2023-08-20
  • 1 回答
  • 0 关注
  • 126 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信