[英]WPF/MVVM Load an UserControl at Runtime
我知道有很多关于我的问题的文章,但我找不到解决方案。 我是WPF的新手 - MVVM,我尝试理解MVVM-Logic。 所以我做了一个小项目来理解这一点。 对于我以后的应用程序,我想动态地将UserControls加载到我的Window。
在我的StartView中,我有一个绑定到StartViewModel。 (绑定在APP.xaml中)
StartView app = new StartView();
StartViewModel context = new StartViewModel();
StartView
<Window x:Class="test.Views.StartView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:test.ViewModel"
Title="Window1" Height="300" Width="516">
<Grid>
<Menu IsMainMenu="True" Margin="0,0,404,239">
<MenuItem Header="_Einstellungen">
<MenuItem Header="Server" />
</MenuItem>
</Menu>
<ContentControl Content="{Binding LoadedControl}" Margin="0,28,0,128" />
</Grid>
</Window>
StartViewModel
namespace test.ViewModel
{
public class StartViewModel : ViewModelBase
{
#region Fields
private UCStastistikViewModel _loadedControl;
#endregion
public StartViewModel()
{
LoadedControl = new UCStastistikViewModel();
}
#region Properties / Commands
public UCStastistikViewModel LoadedControl
{
get { return _loadedControl; }
set
{
if (value == _loadedControl)
return;
_loadedControl = value;
OnPropertyChanged("LoadedControl");
}
}
#endregion
#region Methods
#endregion
}
}
UCStatistikView
<UserControl x:Class="test.Views.UCStatistik"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:test.ViewModel"
mc:Ignorable="d"
d:DesignHeight="188" d:DesignWidth="508">
<UserControl.DataContext>
<vm:UCStastistikViewModel />
</UserControl.DataContext>
<Grid Background="red">
</Grid>
</UserControl>
UCStatistikViewModel
namespace test.ViewModel
{
public class UCStastistikViewModel : ViewModelBase
{
#region Fields
#endregion
public UCStastistikViewModel()
{
}
#region Properties / Commands
#endregion
#region Methods
#endregion
}
}
现在我想在我的StartView的ContentControl中加载我的UCStatistikView。 但是在Startview中只显示Path test.UCStatistikViewModel而不是整个UC可以任何人给我一些想法,我的问题在哪里/哪里出错了?
再见j
您的ViewModel不应该关心UserControls。 相反,让他们持有ViewModels,让WPF解决如何使用DataTemplate绘制ViewModel。
例如,
<Window x:Class="test.Views.StartView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:test.Views"
xmlns:viewmodels="clr-namespace:test.ViewModel"
Title="Window1" Height="300" Width="516">
<Window.Resources>
<DataTemplate DataType="{x:Type viewmodels:UCStastistikViewModel}">
<views:UCStastistikView />
</DataTemplate>
</Window.Resources>
<Grid>
<Menu IsMainMenu="True" Margin="0,0,404,239">
<MenuItem Header="_Einstellungen">
<MenuItem Header="Server" />
</MenuItem>
</Menu>
<ContentControl Content="{Binding LoadedControl}" Margin="0,28,0,128" />
</Grid>
</Window>
另外,摆脱<UserControl.DataContext>
中的<UserControl.DataContext>
。 DataContext
应该通过使用控件的任何内容传入,而不是在UserControl中定义的:)
编辑
根据您对之前关于通过切换ViewModel来切换StartPage内容的回答的评论,您可能有兴趣查看我的这篇文章 。 它标题为Navigation with MVVM
,但是相同的概念适用于切换视图或用户控件
基本上,您将使用ViewModelBase
类型的属性LoadedControl
而不是硬编码它的类型,然后将其设置为您希望在ContentControl中显示的任何对象。 WPF的DataTemplates将负责连接ViewModel的正确视图。
WPF不支持自动解析给定视图模型的视图。 您问题的天真解决方案是直接将UCStatistikView添加到您的StartView并将VM绑定到它
<Window x:Class="test.Views.StartView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:test.ViewModel"
Title="Window1" Height="300" Width="516">
<Grid>
<Menu IsMainMenu="True" Margin="0,0,404,239">
<MenuItem Header="_Einstellungen">
<MenuItem Header="Server" />
</MenuItem>
</Menu>
<UCStatistikView DataContext="{Binding LoadedControl}" Margin="0,28,0,128" />
</Grid>
更详细的方法是实现ViewLocator(视图模型第一种方法)或ViewModelLocator(视图第一种方法)。 定位器自动定位视图并将其绑定到视图模型。 有一些MVVM框架/工具包可以实现这样的定位器。
使用Caliburn.Micro,您开始查看将如下所示
<Window x:Class="test.Views.StartView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:test.ViewModel"
Title="Window1" Height="300" Width="516">
<Grid>
<Menu IsMainMenu="True" Margin="0,0,404,239">
<MenuItem Header="_Einstellungen">
<MenuItem Header="Server" />
</MenuItem>
</Menu>
<ContentControl cm:View.Model="{Binding LoadedControl}" Margin="0,28,0,128" />
</Grid>
cm:View.Model="{Binding LoadedControl}"
附加属性告诉caliburn找到绑定的视图模型的视图,并将ContentControl的Content
属性设置为它。
这是你应该做的:
StartView:
<Window x:Class="test.Views.StartView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:test.ViewModel"
Title="Window1" Height="300" Width="516">
<Grid>
<Menu IsMainMenu="True" Margin="0,0,404,239">
<MenuItem Header="_Einstellungen">
<MenuItem Header="Server" />
</MenuItem>
</Menu>
<UCStatistikView x:Name="myUCStatistikView" Margin="0,28,0,128" />
</Grid>
</Window>
StartViewModel:
namespace test.ViewModel
{
public class StartViewModel : ViewModelBase
{
private UCStastistikViewModel _myControlViewModel;
public StartViewModel()
{
_myControlViewModel = new UCStastistikViewModel();
}
public UCStastistikViewModel MyControlViewModel
{
get { return _myControlViewModel; }
set
{
if (value == _myControlViewModel)
return;
_myControlViewModel = value;
OnPropertyChanged("MyControlViewModel");
}
}
}
}
UCStatistikView:
<UserControl x:Class="test.Views.UCStatistik"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:test.ViewModel"
mc:Ignorable="d"
d:DesignHeight="188" d:DesignWidth="508">
<Grid Background="red">
</Grid>
</UserControl>
您的StartView背后的代码:
this.myUCStatistikView.DataContext = ((StartViewModel)this.DataContext).MyControlViewModel;
在测试了不同的方法之后,我的结论是,如果你有userControls,datacontext绑定的最佳方法是父视图的代码隐藏。
编辑 :ViewModel定位器适用于简单的示例,但如果您的ViewModel必须动态实例化(大多数情况下它的构造函数需要参数),您就无法使用它。 因为这个原因,我个人停止使用定位器。
评论: - http://patelrocky1608.wordpress.com/2013/12/26/how-to-add-custom-control-dynamically-in-wpf/
其中包含用于动态理解UserControl的整个代码..
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.