ViewModel 绑定错误
我遇到错误。场景如下:
- wpf 应用程序加载,ScrollViewer 的内容绑定到 ViewModel 中名为 ActiveFunction(其类型为 UserControl)的属性。在该 ViewModel 的构造函数中为该属性设置自定义控件 (UserCtrl1)。
- 按下一个按钮,发出一个命令,将 ActiveFunction 属性设置为新的 UserControl (UserCtrl2)。即 this.ActiveFunction = new UserCtrl2();
- 新的 UserControl 将作为 ScrollViewer 的内容加载。一切看起来都很好。
- 然后,按下一个按钮,该按钮发出一个命令,将 ActiveFunction 属性设置回原始 UserControl (this.ActiveFunction = new UserCtrl1();)。
- 此时,会引发异常 - “指定元素已经是另一个元素的逻辑子元素。请先断开它。”
任何人都可以帮我解决此问题。如果有帮助的话我很乐意上传整个 VS 解决方案(它不是那么大)。我真的很想了解这项技术的陷阱。我现在似乎是在与技术作斗争,而不是利用它的力量。
干杯
I am experiencing an error. Here is the scenario:
- wpf app loads and the content of a ScrollViewer is bound to a property in a ViewModel called ActiveFunction (which has a type UserControl). A custom control (UserCtrl1) is set for that property in the constructor of that ViewModel.
- A button is pressed which issues a command that sets the ActiveFunction property to a new UserControl (UserCtrl2). That is, this.ActiveFunction = new UserCtrl2();
- The new UserControl is loaded as the content of the ScrollViewer. Everything seems fine.
- Then, a button is pressed which issues a command that sets the ActiveFunction property back to the original UserControl (this.ActiveFunction = new UserCtrl1();).
- At this point, an exception is thrown - "Specified element is already the logical child of another element. Disconnect it first."
Can anyone help me resolve this issue. I'm happy to upload the whole VS solution if that helps (its not that big). I just really want to get an understanding of the pitfalls of this technology. I seem to be fighting against the technology right now, rather than harnessing its power.
Cheers
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我对您描述的场景做了最简单的实现,它对我来说没有错误。我将发布它的代码。请指出您的代码中的差异所在。
I made the most simple implementation of the scenario you described and it works without errors for me. I will post the code for it. Please point out where the differences are in your code.
我进一步调查后发现问题出在 UserCtrl1 中包含的控件上。我对此完全迷失了。所以,对我来说最简单的事情就是在线发布我的项目的 VS 解决方案。这比我试图解释一些我不明白的事情要简单得多(对你来说也更容易)。 点击此处下载。
可以很容易地重新创建异常。运行解决方案 (VS 2010),单击“进度”按钮。然后单击“项目”按钮(这将返回到应用程序首次启动时加载的原始用户控件)。
请注意,UserCtrl1 实际上是 NewWork,UserCtrl2 是 ProgressView。
I've investigated further and found that the problem is with a control which is contained in UserCtrl1. I'm completely lost with this. So, the easiest thing is for me to post my VS solution for the project online. It will be much simpler than me trying to explain something I don't understand (and easier for you too). Click here to download.
The exception can be recreated very easily. Run the solution (VS 2010), click the Progress button. Then click the Project button (which returns to the original user control that is loaded when the app first starts).
Note that UserCtrl1 is actually NewWork and UserCtrl2 is ProgressView.
您收到该错误的原因是您将 ScrollViewer 的内容设置为 UserControl。通过这样做,您将 UserCtrl1 (UserControl) 的父级设置为 ScrollViewer。如果您无法将两个子级设置为 ScrollViewer,那么当您尝试将 UserCtrl2 设置为 ActiveFunction 时就会发生这种情况。您真正应该做的就是充分利用 WPF 中 ViewModel 和 DataTemplate 的强大功能。
根据您发布的代码,我将其更改为使用更多 MVVM 方法。
这是主窗口。
以下是 MainWindow.xaml.cs 背后的代码。基本上我在这里所做的就是将此视图的 DataContext 设置为视图模型。这不是最好的方法,因为您正在对事物进行硬编码。更好的方法是利用数据模板并让 WPF 处理它。
这是 ViewModel 的代码。我使用了从这里找到的 DelegateCommand 的想法 http://www.wpftutorial.net/DelegateCommand。 html。 UserControl1ViewModel 和 UserControl2ViewModel 只是虚拟对象,但您可以使它们实现 INotifyPropertyChanged,然后将其用于数据模板中的绑定。
这里有很多地方可以改进,使 MVVM 世界变得更干净,但这应该可以帮助您解决当前遇到的问题。
The reason you are getting that error is that you are setting the content of the ScrollViewer to be a UserControl. By doing so you are setting the parent of UserCtrl1 (UserControl) to be the ScrollViewer. If you can't set two children to a ScrollViewer which is what is happening when you try to set UserCtrl2 as ActiveFunction. What you should really be doing is too leverage the power of ViewModels and DataTemplates within WPF.
From the code you have posted I changed it to use a more MVVM approach.
Here is the MainWindow.
Here is the code behind for the MainWindow.xaml.cs. Basically what I am doing here is I am setting the DataContext of this view to be the viewmodel. This is not the best way to do it because you are hardcoding things. Better way would be to leverage data templates and let WPF handle it.
Here is the code for the ViewModels. I have used the idea of a DelegateCommand which I found from here http://www.wpftutorial.net/DelegateCommand.html. UserControl1ViewModel and UserControl2ViewModel are just dummy objects but you could make them implement INotifyPropertyChanged and then use that for binding in your datatemplate.
There are many areas here that you could improve upon to make cleaner in the MVVM world but this should help you resolve your issue that you are currently having.