当在mvvm wpf中使用Application.Current.Dispatcher.BeginInvoke启动一个新

本文关键字:启动 一个 BeginInvoke Dispatcher wpf mvvm Current Application 当在 | 更新日期: 2023-09-27 18:03:07

我想显示一个弹出动画,当用户登录到应用程序。我的场景是这样的:我有一个主窗口,它的内容在后端绑定了一个属性SelectedVM。此属性可以有两个值,一个LoginViewModel和两个ContainerViewmodel

现在,我想在登录后显示这个弹出框,直到containerViewModel中出现数据。

我一直在mainwindow.xaml弹出。

我有一个单例类会话,其中我有IsOpen的弹出属性。这是在调用数据加载功能时在LoginViewModel中设置的。我可以看到通过复选框设置的属性,但弹出窗口没有显示。代码如下:

MainWindow.xaml

<Window><Window.Resources>
    <DataTemplate DataType="{x:Type ViewModel:ContainerViewModel}">
        <View:ContainerView></View:ContainerView>
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:LoginViewModel}">
        <View:LoginScreenView></View:LoginScreenView>
    </DataTemplate>
</Window.Resources>
<DockPanel>
    <DockPanel.Background>
        <ImageBrush ImageSource="Images/back.jpg"/>
    </DockPanel.Background>
    <Popup x:Name="WaitScreen" 
           Placement="Center" 
           Visibility="{Binding Path=CurrentSession.IsLoading}"
           >
        <local:LoadAnimation  Background="Black" Margin="110,0,0,0"/>
    </Popup>
    <ContentControl Content="{Binding SelectedVM}"></ContentControl>
    <!--<View:LoginScreenView DockPanel.Dock="Top" Height="100" Width="250" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>-->
</DockPanel></Window>

MainWindowViewModel.cs

 public class MainWindowViewModel: ViewModelBase
{
   public MainWindowViewModel()
   {
       try
       {
           this.CurrentSession.IsLoading = "Hidden";
           this.CurrentSession.PropertyChanged += this.CurrentSession_PropertyChanged;
           this.CurrentSession.VMBInstance = "LoginViewModel";
       }
       catch (Exception ex)
       {
           MessageBox.Show(ex.ToString());
       }
   }     
   void CurrentSession_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
   {
      if(e.PropertyName=="VMBInstance")
      {
          switch (this.CurrentSession.VMBInstance)
          {
              case "LoginViewModel":
                  {
                      this.SelectedVM = new LoginViewModel();
                      break;
                  }
              case "ContainerViewModel":
                  {
                      this.SelectedVM = new ContainerViewModel();
                      break;
                  }
              default:
                  {
                      this.SelectedVM = new LoginViewModel();
                      break;
                  }
          }
      }
   }
   private ViewModelBase selectedVM;
   public ViewModelBase SelectedVM
   {
       get { return selectedVM; }
       set { selectedVM = value; OnPropertyChanged(()=>this.SelectedVM); }
   }
}

LoginViewModel.cs

 class LoginViewModel :ViewModelBase
{


    public LoginViewModel()
    {
        Submit = false;
        this.CurrentSession.IsLoading = "Hidden";
        //this.LoginCommand = new RelayCommand(o => this.worker.RunWorkerAsync(), o => !this.worker.IsBusy);
        //this.worker.DoWork+=this.DoWork;
    }

    #region properties

    private double _currentProgress;
    public double CurrentProgress
    {
        get { return _currentProgress; }
        private set
        {
            if (_currentProgress != value)
            {
                _currentProgress = value;
                OnPropertyChanged("CurrentProgress");
            }
        }
    }
    private Jira Session { get; set; }
    private string _userName;
    public string UserName
    {
        get 
        {
            if (_userName == String.Empty || _userName == null || _password == String.Empty || _password == null)
            {
                Submit = false;
            }
            return _userName; 
        }
        set { 
            _userName = value;
            if (value!=String.Empty || value!=null)
            {
                Submit = true;
            }
            OnPropertyChanged(() => this.UserName); }
    }
    private bool submit;
    public bool Submit
    {
        get { return submit; }
        set { submit = value; OnPropertyChanged(() => this.Submit);}
    }
    private string _password;
    public string Password
    {
        get
        {
            if (_password == String.Empty || _password == null || _userName == String.Empty || _userName == null)
            {
                Submit = false;
            }
            return _password; 
        }
        set 
        {
            _password = value;
            if (value != String.Empty || value != null)
            {
                Submit = true;
            }
            OnPropertyChanged(() => this.Password);
        }
    }

    #endregion
    #region Commands
    public ICommand LoginCommand
    {
        get 
        {
            try
            {
                return new RelayCommand(param => Login()); 
            }
            catch(Exception ed)
            {
            MessageBox.Show("Invalid Login Credentials");
            return null;
            }
        }
    }

    public bool Login()
    {
        try
        {
            //this.Dispatcher.BeginInvoke(new Action(()=> this.CurrentSession.IsLoading=true));

            Application.Current.Dispatcher.BeginInvoke
            (new Action(() => {
                this.CurrentSession.IsLoading = "Visible";
            }));
            this.Session = new Jira("http://jira.mcm.com:8080/", this.UserName, this.Password);
            string test = this.Session.GetAccessToken();
            if (this.Session == null)
            {
                return false;
            }
            this.CurrentSession.JiraObj = this.Session;
            this.CurrentSession.UserName = this.UserName;
            this.CurrentSession.VMBInstance = "ContainerViewModel";
            //this.CurrentSession.IsLoading = true;
            Application.Current.Dispatcher.Invoke(new Action(() => this.CurrentSession.IsLoading = "Hidden"));
            //this.Dispatcher.BeginInvoke(new Action(() => this.CurrentSession.IsLoading = false));
            return true;
        }
        catch (Exception ex)
        {
            MessageBox.Show("Invalid Login Credentials");
            return false;
        }
        finally
        {
            this.Session = null; 
        }
    }
    #endregion
}

有人能告诉我如何使这个弹出可见在一个新的UI线程?

当在mvvm wpf中使用Application.Current.Dispatcher.BeginInvoke启动一个新

您的视图将IsLoading绑定到弹出窗口的Visbility属性,但该属性是string

IsLoading属性更改为Visbility数据类型:

Application.Current.Dispatcher.BeginInvoke
        (new Action(() => {
            this.CurrentSession.IsLoading = Visibility.Visible;
        }));

我通常检查的一些标准内容:

  • 当我绑定时,我的上下文是否正确?
  • 我的属性通知UI的变化(INotifyPropertyChanged)
  • 我的绑定方向正确吗?(单向、双向等)
  • 我的转换器乱了吗?(如果我用的话)。断点并调试。

检查你的属性类型转换,因为你有可见性问题,你应该让它像

private Visibility isloading;
    public Visibility Isloading
    {
    get{return isloading;}
    set{isloading = value;
    OnPropertyChanged("Isloading");
    }

现在你想把它的可见性设置为true,只要输入

this.CurrentSession.Isloading = Visibility.Visible.

如果你想在默认情况下隐藏它,那么在创建属性时将其传递为折叠或隐藏,如我所示:

private Visibility isloading = Visibilty.Collapsed(orHidden);
    public Visibility Isloading
    {
    get{return isloading;}
    set{isloading = value;
    OnPropertyChanged("Isloading");
    }

首先,我会将IsLoading更改为布尔值(它要么正在加载,要么没有)。但是话虽如此,从字符串/布尔值到可见性的方式是通过一个转换器。

因为我建议你把IsLoading改成布尔型,下面是一个布尔型到可见性的转换器

public class BoolToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var b = value as bool?;
        return b.GetValueOrDefault() ?  Visibility.Visible : Visibility.Collapsed ;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value is Visibility)) return false;
        var b = (Visibility)value;
        return b == Visibility.Visible ? true : false ;
    }
}

然后可以在资源部分中包含转换器

你可以这样使用

 <Popup Visibility="{Binding IsLoading, Converter={StaticResource BoolToVisibilityConverter}}"/>