【问题标题】:WPF page fixed layout with MVVM带有 MVVM 的 WPF 页面固定布局
【发布时间】:2015-04-20 02:29:10
【问题描述】:

我有一个带有 MVVM 的 WPF 应用程序,它有几个具有通用布局的页面,例如页面标题和导航按钮(每个页面的中间部分不同)。 如何实现一次固定的页面布局并使用 MVVM 在不同的页面中进行扩展?

【问题讨论】:

    标签: wpf


    【解决方案1】:

    在我看来,最好的方法是创建一个主窗口或页面,然后使用内容控件和数据模板在其中呈现用户控件。将内容控件绑定设置为主窗口视图模型上的属性。当然,您需要一个 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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多