Neha
Neha

Reputation: 821

Pop up not getting opened when a new thread is started using Application.Current.Dispatcher.BeginInvoke in mvvm wpf

I want to show a pop up having animation when the user does log in into the application. My scenario is like this: I have main window whose content is bound with a property SelectedVM in the backend. This property can have two values, one LoginViewModel, and two ContainerViewmodel.

Now, I want to show this pop up after login till data appears in containerViewModel.

I have kept pop up in mainwindow.xaml.

I have a singleton class session in which I have property for IsOpen of pop up. This I set in LoginViewModel when data loading functionality is called. I can see the property being set through a checkbox but pop up does not show up. Below is the code.

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
}

Can someone please tell me how to make this pop up visible in a new UI Thread?

Upvotes: 0

Views: 251

Answers (3)

Niels Filter
Niels Filter

Reputation: 4528

Your view binds the IsLoading to the Popup's Visbility property, but the property is a string.

Change IsLoading property to Visbility data type:

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

Some standard things I usually check:

  • Is my context correct when I bind?
  • Does my property notify the UI of the change (INotifyPropertyChanged)
  • Is my Binding Direction correct? (one-way, two-way etc.)
  • Are my properties the correct data type
  • Is my converter messing around? (if I'm using one). Breakpoint and debug it.

Upvotes: 2

TYY
TYY

Reputation: 2716

First thing first, I would change IsLoading to a boolean (it is either loading or it is not). But with that said, the way to go from string/ boolean to Visibility is via a converter.

Since I am advocating you change the IsLoading to boolean, below is a boolean to visibility converter

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 ;
    }
}

You can then include the converter in the resource section

And you can use it like so

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

Upvotes: 0

DeshDeep Singh
DeshDeep Singh

Reputation: 1853

Just check your propert type cast, since you have visibility issue you should make it something like

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

now where ever you want to set its visibility true, just type

this.CurrentSession.Isloading = Visibility.Visible.

also if you want bydefault it to be hidden then just while creating property pass as collapsed or hidden, as i have shown:

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

Upvotes: 0

Related Questions