【发布时间】:2015-04-20 02:29:10
【问题描述】:
我有一个带有 MVVM 的 WPF 应用程序,它有几个具有通用布局的页面,例如页面标题和导航按钮(每个页面的中间部分不同)。 如何实现一次固定的页面布局并使用 MVVM 在不同的页面中进行扩展?
【问题讨论】:
标签: wpf
我有一个带有 MVVM 的 WPF 应用程序,它有几个具有通用布局的页面,例如页面标题和导航按钮(每个页面的中间部分不同)。 如何实现一次固定的页面布局并使用 MVVM 在不同的页面中进行扩展?
【问题讨论】:
标签: wpf
在我看来,最好的方法是创建一个主窗口或页面,然后使用内容控件和数据模板在其中呈现用户控件。将内容控件绑定设置为主窗口视图模型上的属性。当然,您需要一个 INotifyPropertyChanged 的实现,然后是主窗口或应用程序视图模型、一些子视图模型、主窗口或页面中的内容控件,然后是表示您的视图的用户控件......这样:
public abstract class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string property)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs(property));
}
}
[Conditional("DEBUG")]
[DebuggerStepThrough]
protected virtual void VerifyPropertyName(string property)
{
if (TypeDescriptor.GetProperties(this)[property] == null)
{
throw new Exception(property + " property doesn't exist!");
}
}
}
public interface IPageViewModel
{
string Name { get; }
}
public class Page1ViewModel : ObservableObject, IPageViewModel
{
public string Name { get { return "View 1"; } }
}
public class Page2ViewModel : ObservableObject, IPageViewModel
{
public string Name { get { return "View 1"; } }
}
public class ApplicationViewModel : ObservableObject
{
private IPageViewModel currentViewModel;
public IPageViewModel CurrentViewModel
{
get
{
return this.currentViewModel =
this.currentViewModel
?? new Page1ViewModel();
}
set
{
this.currentViewModel = value;
OnPropertyChanged("CurrentViewModel");
}
}
public ApplicationViewModel()
{
this.CurrentViewModel = new Page1ViewModel()
}
}
您的主窗口或页面会将其视图模型 (DataContext) 设置为 ApplicationViewModel 的实例。然后内容控件将绑定到 ApplicationViewModel 的 CurrentViewModel 属性,如下所示:
<Window x:Class="WpfScratchApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:app="clr-namespace:WpfScratchApp"
Title="MainWindow" Height="350" Width="525"
DataContext="{DynamicResource AppViewModel}"
>
<Window.Resources>
<ResourceDictionary>
<app:ApplicationViewModel x:Key="AppViewModel" />
</ResourceDictionary>
</Window.Resources>
<Grid>
<!-- Buttons and stuff -->
<ContentControl Content="{Binding CurrentViewModel}" />
</Grid>
</Window>
然后,创建与每个视图对应的 UserControl:
<UserControl x:Class="WpfScratchApp.Views.Page1View"
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"
mc:Ignorable="d"
d:DesignHeight="150" d:DesignWidth="150">
<!-- Cool controls and stuff in here... -->
</UserControl>
(创建一个与 Page2ViewModel 对应的类似模型,称为“Page2View”。)然后,将视图模型映射到 app.xaml 或合并字典中的视图。
<Application x:Class="WpfScratchApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:PortfolioManager"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type vm:Page1ViewModel}">
<views:Page1View />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:Page2ViewModel}">
<views:Page2View />
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
当您更改应用程序视图模型中的 CurrentViewModel 属性时,它应该更改控件控件的绑定值。 WPF 将使用 CurrentViewModel 属性所代表的类型对应的数据模板来呈现内容。
因此,您可以在主窗口中设置所有按钮并对其进行编码以在 CurrentViewModel 上进行操作。然后,根据您要显示的内容更改 CurrentViewModel。
【讨论】: