我正在开发一个 WPF 登录表单。我有一个带有两个选项卡的选项卡控件:
tab1) 包含登录的输入(用户名和密码文本框/标签)
tab2) 包含一个自定义动画,用作进度条
一旦用户捕获了所有信息并在登录按钮的单击事件中单击登录,我将活动选项卡设置为 tab2 并向用户显示进度条。如果在此步骤中发生错误,我想将用户返回到 tab1,这就是我收到以下错误的地方:
无效操作异常(调用线程无法访问此对象,因为不同的线程拥有它。)
请建议我如何杀死线程或任何其他解决方法来帮助解决我的问题
我的代码:
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;
}));
}
}