我不是很确定我的问题/错误出在哪里。 我正在使用WPF和MVVM模式结合,在登录时遇到了问题。
我的第一次尝试很好用。我有几个窗口,每个窗口都有自己的ViewModel。 在登录ViewModel中,我运行了以下代码:
PanelMainMessage = "Verbindung zum Server wird aufgebaut";
PanelLoading = true;
_isValid = _isSupportUser = false;
string server = Environment.GetEnvironmentVariable("CidServer");
string domain = Environment.GetEnvironmentVariable("SMARTDomain");
try
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, server + "." + domain))
{
// validate the credentials
PanelMainMessage = "username und passwort werden überprüft";
_isValid = pc.ValidateCredentials(Username, _view.PasswortBox.Password);
PanelMainMessage = "gruppe wird überprüft";
_isSupportUser = isSupport(Username, pc);
}
}
catch (Exception ex)
{
//errormanagement -> later
}
if (_isValid)
{
PanelLoading = false;
if (_isSupportUser)
_mainwindowviewmodel.switchToQuestionView(true);
else
_mainwindowviewmodel.switchToQuestionView(false);
}
else
PanelMainMessage = "Verbindung zum Server konnte nicht hergestellt werden";
该部分连接到Active Directory,首先检查登录是否成功,然后检查用户是否具有特定的AD组(在isSupport方法中)。
我在视图中有一个显示,类似于进度条。当PanelLoading等于true时它是活动的。
到目前为止一切正常。
然后我创建了一个带有contentcontrol的主窗口,并将我的视图更改为用户控件,以便可以交换它们。(意图是不为每个视图打开/创建一个新窗口)。
现在执行代码时,我的GUI会被阻塞,直到该部分被执行。我尝试了几种方法...
Moving the code snippet into an additional method and starting it as an own thread:
Thread t1 = new Thread(() => loginThread()); t1.SetApartmentState(ApartmentState.STA); t1.Start();
When I do it this way, I get an error that a ressource is owned by an another thread and thus cannot be accessed. (the calling thread cannot access this object because a different thread owns it)
Then, instead of an additional thread, trying to invoke the login part; login containing the previous code snippet
Application.Current.Dispatcher.Invoke((Action)(() => { login(); }));
That does not work. At least not how I implemented it.
After that, I tried to run only the main part of the login snippet in a thread and after that finished, raising an previously registered event, which would handle the change of the content control. That is the part, where I get the error with the thread accessing a ressource owned by another thread, so I thought, I could work around that.
void HandleThreadDone(object sender, EventArgs e) { if (_isValid) { PanelLoading = false; _mainwindowviewmodel.switchToQuestionView(_isSupportUser); } else PanelMainMessage = "Verbindung zum Server konnte nicht hergestellt werden"; }
And in the login method I would call ThreadDone(this, EventArgs.Empty); after it finished. Well, I got the same error regarding the ressource owned by an another thread.
现在我在这里,寻求帮助...
我知道我的代码不是最漂亮的,也至少两次违反了MVVM模式的思想。此外,我对Invoke方法的理解很少,但我已经尽力并在stackoverflow和其他网站上搜索了一段时间(2-3小时),但没有成功。
为了指定线程错误发生的位置:
_mainwindowviewmodel.switchToQuestionView(_isSupportUser);
which leads to the following method
public void switchToQuestionView(bool supportUser)
{
_view.ContentHolder.Content = new SwitchPanel(supportUser);
}
这也是一种情况,我没有使用数据绑定。我改变了我的内容控件(contentcontrol)的内容:
<ContentControl Name="ContentHolder"/>
我该如何使用数据绑定来实现这个功能?属性应该具有ContentControl类型吗?我没有真正找到答案。将其更改为数据绑定,能解决线程所有权的错误吗?
项目结构如下: Main View是入口点,在构造函数中设置数据上下文为mainviewmodel,此时创建了它。主视图有一个contentcontrol,在其中交换用户控件,例如我的视图。
从我的mainviewmodel中,我在开始时设置contentcontrol的内容为usercontrol login,它在其构造函数中创建一个viewmodel,并将其设置为数据上下文。
这些代码片段来自于我的loginviewmodel。希望这可以帮助你。
我认为我已经找到了一种解决方法,但它仍然无法工作。我忘记了计时器在后台的工作方式,所以也可以通过这种方式解决。