将ContentControl绑定到UserControl,并重用相同的实例
本文关键字:实例 绑定 ContentControl UserControl | 更新日期: 2023-09-27 18:06:30
我试图绑定一个ContentControl的内容到一个UserControl我已经在我的ViewModel实例化。我不能使用绑定到ViewModel的方法,然后有UserControl是ViewModel的DataTemplate,因为我需要ContentControl的内容能够经常改变,使用UserControls/Views的相同的实例,而不是实例化视图每次我重新绑定。
然而,当设置usercontrol -属性为UserControl-instance时,然后当视图被渲染/数据绑定时,我得到:必须在附加到新的父可视化之前从当前父可视化断开指定的子。尽管我之前没有将这个UserControl添加到任何地方,但我只是在之前创建了这个实例并将其保存在内存中。
有没有更好的方法来实现我正在做的事情?
在ViewModel
public class MyViewModel : INotifyPropertyChanged
{
//...
private void LoadApps()
{
var instances = new List<UserControl>
{
new Instance1View(),
new Instance2View(),
new Instance3View(),
};
SwitchInstances(instances);
}
private void SwitchInstances(List<UserControl> instances)
{
CenterApp = instances[0];
}
//...
private UserControl _centerApp;
public UserControl CenterApp
{
get { return _centerApp; }
set
{
if (_centerApp == value)
{
return;
}
_centerApp = value;
OnPropertyChanged("CenterApp");
}
}
//...
}
View.xaml
<ContentControl Content="{Binding CenterApp}"></ContentControl>
注释太长
根据@Kent在你的评论中所说的,MVVM的全部要点是将视图模型与视图相关的东西(控件)断开连接,这阻碍了GUI应用程序的测试能力。因此,拥有UserControl/Button/任何与图形视图相关的项否定了MVVM的整个原则。
如果使用MVVM,你应该遵守它的标准,然后重新解决你的问题。
- 使用MVVM通常有1个视图<-> 1个视图模型
- 视图知道它的视图模型(通常通过DataContext)。反向不应该被编码到。
- 您尝试在视图模型中放置控制视图的逻辑,以允许测试逻辑(命令和INPC属性)
…还有更多。它在视图模型没有视图相关的东西的范围内是非常具体的,例如视图模型中甚至没有属性,比如Visibility
。您通常持有bool
,然后在视图中使用转换器将其切换到Visibility
对象。
多读一点关于MVVM的知识肯定会对你有帮助,
现在有一些东西可以解决你当前的问题:
在MVVM结构之后,
你会有ViewModels,比如
- Main:
MyViewModel
- 从一个基中派生所有的实例viewmodel,以允许它们保存在一个列表中。
- 列出或单独持有
Instance1ViewModel
,Instance2ViewModel
,Instance3ViewModel
在MyViewModel
(要么创建它自己,或者如果你使用IOC容器让它注入) - 让
MyViewModel
暴露一个属性,就像你发布的例子:
的例子:
// ViewModelBase is the base class for all instance View Models
private ViewModelBase _currentFrame;
public ViewModelBase CurrentFrame {
get {
return _currentFrame;
}
private set {
if (value == _currentFrame)
return;
_currentFrame = value;
OnPropertyChanged(() => CurrentFrame);
}
}
- 现在在你的
MyView.xaml
视图文件中,你应该(不必是顶级的)将顶级数据文本设置为你的MyViewModel
你的视图的xaml可以这样声明:
的例子:
...
<Window.Resources>
<DataTemplate DataType="{x:Type local:Instance1ViewModel}">
<local:Instance1View />
</DataTemplate>
<DataTemplate DataType="{x:Type local:Instance2ViewModel}">
<local:Instance2View />
</DataTemplate>
<DataTemplate DataType="{x:Type local:Instance3ViewModel}">
<local:Instance3View />
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content="{Binding Path=CurrentFrame}" />
</Grid>
...
- !。现在,您只需切换视图模型中的
CurrentFrame
属性,并使其指向三个实例视图模型中的任何一个,视图将相应地更新。
这让你得到一个MVVM兼容的应用程序,对于你的工作周围的其他问题,不必基于DataTemplate动态地重新创建视图,你可以遵循这里建议的方法,并扩展它为您自己的使用。