提问者:小点点

如何更新Blazor视图?


我正在用ASP.NET Core WebAssembly试用MVVM模式,因此构建了一个ASP.NET Core托管应用程序。 我试图使用“InotfiyPropertyChanged”,我在一个UWP应用程序中使用了相同的模型,它起到了作用。 出于学习的目的,我希望使用相同的模式在ASP.NET核心Blazor WebAssembly应用程序中重新创建它。

以下问题,当启动应用程序时,应将“日期时间”更新为当前时间。 每次我启动服务器应用程序时,我没有得到从现在开始应该的时间,它总是相同的时间,我第一次运行应用程序(12am)。

@page "/"
@using ...

<div class="region-top-left">
   <p>@clockViewModel.CurrentTime</p>   <!-- From here the 12:00 comes -->
</div>

@code 
{
    ClockViewModel clockViewModel = new ClockViewModel();
    ClockModel clockModel = new ClockModel();

    protected override Task OnInitializedAsync() 
    {
        clockViewModel.Initialize(clockModel);
        return base.OnInitializedAsync();
    }
}

在index.razor内部调用“initialize”方法,我希望返回当前的日期时间。 还试图创建一个从未被击中的断点。

    public class ClockViewModel : PropertyChangedBase
    {
        private ClockModel model;
        private string currentTime { get; set; }
        public string CurrentTime
        {
            get
            {
                return currentTime;
            }
            set
            {
                if (currentTime != value)
                {
                    currentTime = value;
                    NotifyPropertyChanged();
                }
            }
        }
        internal void Initialize(ClockModel model)
        {
            this.model = model;
            updateTime();
            model.PropertyChanged += ModelPropertyChanged;
        }

        private void ModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(model.CurrentTime))
            {
                updateTime();
            }
        }

        private void updateTime()
        {
            CurrentTime = model.CurrentTime.ToString("h:mm");
        }
    }

这是处理Web应用程序中INotifyPropertyChanged的错误方法吗?


共2个答案

匿名用户

在Model和ViewModel之间使用INotfiyPropertyChanged并不是MVVM的主要部分。 这是可以做到的,但往往是以其他方式做到的。

您仍然需要从ViewModel更新到View:

protected override Task OnInitializedAsync() 
{
    clockViewModel.Initialize(clockModel);
    clockViewModel.PropertyChanged += ViewModelPropertyChanged;

    return base.OnInitializedAsync();
}

private void ViewModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
   // you may not need the if()
   if (e.PropertyName == nameof(clockViewModel.CurrentTime))
   {
       // Invoke because Model/ViewModel may be running on other Threads
       InvokeAsync(StateHasChanged);
   }
}

您可以省略对属性名的检查,并为ViewModel中的每个更改调用StateHasChanged。

匿名用户

我会说,是的,这是错误的做法。 通常,您会使用javascript来执行类似的操作。 关于Web应用程序,您需要了解的主要事情是您有一个服务器和一个客户机。 与UWP相反,UWP基本上所有的事情都在客户端上处理。 这样,一旦您从服务器获得请求,就不会再处理更多的C#,直到您再次调用服务器。 此外,只有在应用程序启动时才会点击OnInitializedAsync