C# 如何将按钮更改为动画加载图标?

C# 如何将按钮更改为动画加载图标?,c#,wpf,asynchronous,C#,Wpf,Asynchronous,标题说明了一切 我真的在这里迷路了。。。我用WPF来做这个。我已经尝试使用后台工作程序、线程、Dispatcher.BeginInvoke和async Wait来实现我的目标,但没有效果。。。我在async Wait中定居下来,因为我认为这更容易在这里发布,所以 这是我的密码: C代码隐藏: private async void btnLogin_Click(object sender, RoutedEventArgs e) { btnLogin.Visibility = Visibil

标题说明了一切

我真的在这里迷路了。。。我用WPF来做这个。我已经尝试使用后台工作程序、线程、Dispatcher.BeginInvoke和async Wait来实现我的目标,但没有效果。。。我在async Wait中定居下来,因为我认为这更容易在这里发布,所以

这是我的密码:

C代码隐藏:

private async void btnLogin_Click(object sender, RoutedEventArgs e)
{
    btnLogin.Visibility = Visibility.Hidden;
    RollingIcon.Visibility = Visibility.Visible;

    await DoLogin();

    btnLogin.Visibility = Visibility.Visible;
    RollingIcon.Visibility = Visibility.Collapsed;
}

private Task DoLogin()
{
  return TaskEx.Run(() => {
      //code for validation if no nulls
      this.ViewModel.ValidateUserCredentials();
  });
}
XAML

显然,System.InvalidOperationException将弹出,因为当我尝试在另一个线程上填充ViewModel时,ViewModel是在主线程中创建的

请引导我走上正确的道路,从黑暗面拯救我

任何事情都会很感激的


TIA回答这个问题:

多亏了Daniel,我意识到在VM中放置一个新线程比视图更合适。我重新设计了我的设计,现在看起来是这样的:

虚拟机

查看XAML

        <Button x:Name="btnLogin"
                Content="Login" Visibility="{Binding ShowBusyIcon, Converter={StaticResource inverseVisibilityConverter}}" />
        <local:SpinningAnimation  x:Name="RollingIcon" 
                                  Grid.Column="1" 
                                  Width="40" Height="40" 
                                  Margin="10,10,10,0" 
                                  Visibility="{Binding ShowBusyIcon, Converter={StaticResource  bool2VisibilityConverter}}" 
                                  Style="{DynamicResource SpinningAnimationStyle1}" />

如果您使用的是MVVM模式,我认为您犯了一些可怕的错误。您正试图从ViewModel在视图UI线程中运行任务?甚至可视性也应与属性绑定。。如果需要隐藏,请使用其他转换器。对于登录,我会编写一个服务类或类似的东西,并将按钮绑定到使用它的命令。@Daniel-这给了我一个想法。我会试试的!谢谢虽然那次否决票真的很伤人没问题。。为了更好地理解,请参阅一些基本的MVVM示例,就像这里已经发布的许多示例一样。如果确实需要从另一个线程访问某些内容,可以使用Dispatcher调用。。但在此之前,最好先了解线程。我没有投你反对票,哈哈
 public void ValidateUserCredentials()
        {
            BackgroundWorker bgw = new BackgroundWorker();
            bgw.DoWork += new DoWorkEventHandler(Bgw_DoWork);
            bgw.RunWorkerCompleted += Bgw_RunWorkerCompleted;
            bgw.RunWorkerAsync();
        }
        private void Bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (IsLoginSuccessful == true)
            {
                _controller.CloseViewModel(this);
                _controller.InitWincollect();
            }
        }

        private void Bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            ShowBusyIcon = true;
            IsLoginSuccessful = _controller.ValidateUserCredential();
        }
        bool _isLoginSuccessful = false;
        private bool _showBusyIcon;

        public bool ShowBusyIcon
        {
            get { return _showBusyIcon; }
            set { _showBusyIcon = value; NotifyPropertyChanged("ShowBusyIcon"); }
        }

        public bool IsLoginSuccessful
        {
            get { return _isLoginSuccessful; }
            set { _isLoginSuccessful = value; NotifyPropertyChanged("IsLoginSuccessful"); }
        }
        <Button x:Name="btnLogin"
                Content="Login" Visibility="{Binding ShowBusyIcon, Converter={StaticResource inverseVisibilityConverter}}" />
        <local:SpinningAnimation  x:Name="RollingIcon" 
                                  Grid.Column="1" 
                                  Width="40" Height="40" 
                                  Margin="10,10,10,0" 
                                  Visibility="{Binding ShowBusyIcon, Converter={StaticResource  bool2VisibilityConverter}}" 
                                  Style="{DynamicResource SpinningAnimationStyle1}" />