I'm developing a WPF Login form.I have a tab control with two tabs:
tab1) Contains the inputs for login(user name and password text box/labels)
tab2) Contains a custom animation which is used as the progress bar
Once the user captures all the info and clicks Login in the Login button's click event I set the active tab to tab2 and the progress bar is shown to the user. If an error occurs during this step I would like to return the user to tab1 and this is where I get the following error:
Invalid Operation Exception (The calling thread cannot access this object because a different thread owns it.)
Please advice how I can kill the thread or any other work around to help fix my problem
My code:
public partial class LogonVM : ILogonVM
{
private IWebService _webService;
private static TabControl loaderTabs;
private string userName = String.Empty;
public string UserName
{
get { return userName; }
set
{
userName = value;
OnPropertyChanged("UserName", true);
}
}
private SecureString password = new SecureString();
public SecureString Password
{
get { return password; }
set
{
password = value;
OnPropertyChanged("Password", true);
}
}
public MinimalLogonViewModel(MinimalLogonView view,IWebService webService)
{
_webService = webService;
View = view;
view.DataContext = this;
loaderTabs = (TabControl)this.View.FindName("loaderTabs");
}
catch (Exception eX)
{
MessageBox.Show(eX.Message);
}
}
protected virtual void OnPropertyChanged(string propertyName, bool raiseCanExecute)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
if (raiseCanExecute)
LogonCommand.RaiseCanExecuteChanged();
}
private void Logon(object parameter)
{
SetActiveTab(TabType.Loader);
_messageBroker.onAuthenticated += new EventHandler(_MessageBroker_onAuthenticated);
Task.Execute((DispatcherWrapper)View.Dispatcher,
() => _webService.Authenticate(userName, password.ConvertToUnsecureString()),
(ex) =>
{
if (ex != null)
{
//This is where I'm having issues
//If an error occurs I want to switch back to the Login tab which will enable the user to try Login again
//This does not throw an error but it also doesn't show the Login tab
SetActiveTab(TabType.Login);
}
else
{
//No error perform additional processing
}
});
}
private void SetActiveTab(TabType type)
{
//If I leave the code as simply:
//loaderTabs.SelectedIndex = (int)type;
//I get an error when seting the tab for the second time:
//Invalid Operation Exception (The calling thread cannot access this object because a different thread owns it.)
loaderTabs.Dispatcher.Invoke((Action)(() =>
{
loaderTabs.SelectedIndex = (int)type;
}));
}
}