我来自Angular 2和C#后端背景,所以对于Angular方面,我习惯使用异步函数和代码,以及C#背景我理解基本库。
我正在尝试创建一个包含按钮和加载gif的简单页面。你点击加载gif出现的按钮,10秒后它就会消失。
我可以让加载开始没问题,但是异步代码的性质会跳过执行并立即使gif消失。
如何启动微调器/使gif可见,以非ui-blocking方式等待10秒,然后以线程安全的方式结束动画/ gif可见性?
查看 - 型号代码:
public class LoadingViewModel: INotifyPropertyChanged
{
private Visibility _loadingState;
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public LoadingViewModel()
{
this._loadingState = Visibility.Collapsed;
}
public Visibility LoadingState
{
get {
return this._loadingState;
}
set {
this._loadingState = value;
this.OnPropertyChanged();
}
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
// Raise the PropertyChanged event, passing the name of the property whose value has changed.
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
MainView.xaml.cs:
public LoadingViewModel LoadingViewModel { get; set; }
public MainPage()
{
this.InitializeComponent();
this.LoadingViewModel = new LoadingViewModel();
}
private async Task BeginLoading()
{
LoadingViewModel.LoadingState = Visibility.Visible;
await Task.Factory.StartNew(() =>
{
Task.Delay(TimeSpan.FromSeconds(10));
}).ContinueWith(EndLoadingState);
}
//Updated and works but is there a better way?
private async Task BeginLoading()
{
LoadingViewModel.LoadingState = Visibility.Visible;
await Task.Factory.StartNew(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(10));
await EndLoadingState(); //<-- New EndLoadingState doesn't accept parms
});
}
private async void EndLoadingState(object state)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
LoadingViewModel.LoadingState = Visibility.Collapsed;
});
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
await BeginLoading();
}
最后是一个带有我的按钮和图像的基本堆栈面板:
<StackPanel Margin="10,144,0,144">
<Button Content="Begin Loading for 10 seconds" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" Height="157" Width="366" FontSize="22" Background="{x:Null}" BorderThickness="5" BorderBrush="#FF58FF00" Click="Button_Click"/>
<Image HorizontalAlignment="Center" Height="250" VerticalAlignment="Center" Width="250" Margin="0,25,0,0" Stretch="UniformToFill" Source="Assets/LoadingBubbles.gif" Visibility="{x:Bind Path=LoadingViewModel.LoadingState, Mode=TwoWay}"/>
</StackPanel>
答案 0 :(得分:3)
首先,尝试在bool
而不是LoadingViewModel
中使用Visibility
属性,因为后者是UI属性。您通常不希望在 ViewModel 中使用它。如果您的目标Windows 10版本是 14393 或更高版本,则可以直接绑定它而不使用BoolToVisibilityConverter
。并且绑定也不需要TwoWay
。
Visibility="{x:Bind Path=LoadingViewModel.IsLoading, Mode=OneWay}"
其次,XAML绑定实际上会负责将更新的值分派到UI线程上。因此,您也可以摆脱Dispatcher.RunAsync
并使用正常的void
方法
private void EndLoadingState(object state)
{
LoadingViewModel.IsLoading = false;
}
最后,您的BeginLoading
方法(最好将其重命名为BeginLoadingAsync
)可以简化为
private async Task BeginLoadingAsync()
{
LoadingViewModel.IsLoading = true;
await Task.Delay(TimeSpan.FromSeconds(10));
EndLoadingState();
}
希望这有帮助!