C# 将ContentControl绑定到UserControl,并重用同一实例
我试图将ContentControl的内容绑定到我在ViewModel中实例化的UserControl。我不能使用绑定到ViewModel的方法,然后让UserControl成为ViewModel的DataTemplate,因为我需要ContentControl的内容能够频繁更改,使用UserControl/Views的相同实例,而不是在每次重新绑定时实例化视图 但是,当将UserControl属性设置为UserControl实例时,以及当视图呈现/数据绑定时,我得到:必须先断开指定子项与当前父项视觉的连接,然后再附加到新父项视觉。尽管我之前没有将这个UserControl添加到任何地方,但我只是在前面创建了这个实例并将其保存在内存中 有没有更好的方法来实现我正在做的事情 在ViewModel中C# 将ContentControl绑定到UserControl,并重用同一实例,c#,wpf,xaml,binding,contentcontrol,C#,Wpf,Xaml,Binding,Contentcontrol,我试图将ContentControl的内容绑定到我在ViewModel中实例化的UserControl。我不能使用绑定到ViewModel的方法,然后让UserControl成为ViewModel的DataTemplate,因为我需要ContentControl的内容能够频繁更改,使用UserControl/Views的相同实例,而不是在每次重新绑定时实例化视图 但是,当将UserControl属性设置为UserControl实例时,以及当视图呈现/数据绑定时,我得到:必须先断开指定子项与当前父
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");
}
}
//...
}
公共类MyViewModel:INotifyPropertyChanged
{
//...
私有void LoadApps()
{
var实例=新列表
{
新建Instance1View(),
新建Instance2View(),
新建Instance3View(),
};
切换实例(实例);
}
私有void开关实例(列表实例)
{
CenterApp=实例[0];
}
//...
私人用户控制(centerApp),;
公共用户控制中心应用程序
{
获取{return\u centerApp;}
设置
{
如果(_centerApp==值)
{
返回;
}
_centerApp=价值;
OnPropertyChanged(“CenterApp”);
}
}
//...
}
在View.xaml中
<ContentControl Content="{Binding CenterApp}"></ContentControl>
评论太长 基于@Kent在您的评论中所说的内容,MVVM的整个要点是将视图模型与视图相关的东西(控件)断开连接,这会阻碍GUI应用程序的测试能力。因此,用户控件/按钮/任何与图形视图相关的项目都否定了MVVM的整个原则 如果使用MVVM符合其标准,则应该重新解决您的问题
可见性
。您通常持有bool
,然后在视图中使用转换器将其切换到可见性
对象
多读一点MVVM肯定会对您有所帮助
现在,让我们来谈谈您当前的问题:
遵循MVVM结构
您将拥有ViewModels,例如
- Main:
MyViewModel
- 从基础派生所有实例视图模型,以允许它们保留在列表中
- 在
中分别列出或保持MyViewModel
,Instance1ViewModel
,Instance2ViewModel
(可以自己创建,也可以使用IOC容器将其注入)Instance3ViewModel
- 让
像您发布的示例一样公开属性: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);
}
}
...
<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>
...
- 现在,在您的
View文件中,您应该(不必是顶级的)将顶级数据上下文设置为您的MyView.xaml
MyViewModel
- 然后,您的视图的xaml可以声明为:
// 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);
}
}
...
<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动态重新创建视图的另一个问题,您可以按照建议的方法进行操作,并将其扩展以供自己使用。“我在ViewModel中实例化的用户控件”您做得不对。在主视图模型中实例化次视图模型,将内容控件绑定到该模型,并使用内容模板显示其可视化树。VM不应该创建视图(或依赖于视图)。@KentBoogaart,据我所知(在我的问题中说):我不能使用绑定到ViewModel的方法,然后让UserControl成为ViewModel的DataTemplate,因为我需要ContentControl的内容能够频繁更改,使用相同的UserControls/Views实例,而不是在每次重新绑定时实例化视图。还是我不明白datatemplate是如何工作的?谢谢你的详细回答!我理解所有这些,这是我第一次尝试修复它——使用视图作为ViewModel的数据模板。但是,在视图中,我将VisualStates绑定到ViewModel属性,当我将绑定到ContentControl的ViewModel切换到另一个VM,然后将其切换回时,内存中似乎有两个视图实例,它们都将ViewState绑定到我的ViewModel。每次我重新绑定ContentControl时,它都会创建一个新的视图实例。我找不到一个解决方案,可以在ContentControl中使用相同的视图实例。这时我尝试将视图实例绑定到ContentControl,而不是ViewModel,从而打破了MVVM模式。@cederlof没有问题。我理解您在从视图模型切换视图时保留视图的问题。你看过我文章最后一段的链接了吗。这个问题和你的问题一模一样,有一些有用的答案。您可以尝试Rachael的示例,并将其应用到您的容器中,以获得您的需求和否