码迷,mamicode.com
首页 > 其他好文 > 详细

WPF: 在MVVM中使用Navigtaion

时间:2014-05-18 00:29:41      阅读:397      评论:0      收藏:0      [点我收藏+]

标签:style   blog   class   code   c   java   

Navigation可以很方便的在页面间进行切换,但是在MVVM模式下,使用Naviation会有一个问题,切换的逻辑需要在ViewModel层完成,但是Navigation需要知道页面的实例或者Uri才能进行切换,那我们如何在ViewModel与UI分离的情况下,用Navigation完成页面的切换呢?

假如有一个程序如下所示,点击Switch之后会从Summary Page切换到另一个页面Detail Page:

bubuko.com,布布扣

bubuko.com,布布扣

在MVVM中,我们需要有三个ViewModel,一个是SummaryViewModel对应SummaryPage, 一个是DetailViewModel对应DetailPage,再加上一个ControlViewModel负责通过改变CurrentPageViewModel来实现逻辑数据的切换并将其反应到UI,如下所示:

bubuko.com,布布扣
public class SummaryViewModel
    {
        public ObservableCollection<SummaryModel> Summaries { get; set; }
        
        public SummaryViewModel()
        {
            Summaries = new ObservableCollection<SummaryModel>();
        }
    }
bubuko.com,布布扣
bubuko.com,布布扣
public class DetailViewModel
    {
        public ObservableCollection<DetailModel> Details { get; set; }
        
        public DetailViewModel()
        {
            Details = new ObservableCollection<DetailModel>();
        }
    }
bubuko.com,布布扣
bubuko.com,布布扣
public class NavigationControlViewModelBase : ViewModelBase
    {
        private object currentPageViewModel;
        public object CurrentPageViewModel 
        { 
            get
            {
                return currentPageViewModel;
            } 
            set 
            { 
                currentPageViewModel = value;
                RaisePropertyChanged(() => CurrentPageViewModel); 
            } 
        }
}


public class ControlViewModel : NavigationControlViewModelBase
    {
        private SummaryViewModel summary;
        public SummaryViewModel Summary { get { return summary; } set { summary = value; RaisePropertyChanged(() => Summary); } }

        private DetailViewModel detail;
        public DetailViewModel Detail { get { return detail; } set { detail = value; RaisePropertyChanged(() => Detail); } }


        public ControlViewModel()
        {
            SwitchCommand = new RelayCommand(Switch);
            Summary = new SummaryViewModel();
            Detail = new DetailViewModel();
            CurrentPageViewModel = Summary;

            GenerateData();
        }

        public ICommand SwitchCommand {get;set;}
        
        private void Switch()
        {
            if (CurrentPageViewModel == Summary)
            {
                CurrentPageViewModel = Detail;
            }
            else
            {
                CurrentPageViewModel = Summary;
            }
        }

        private void GenerateData()
        {
            var ran = new Random();
            Summary.Summaries.Clear();
            Detail.Details.Clear();

            for (int i = 0; i < 100; i++)
            {
                Summary.Summaries.Add(new SummaryModel() { ID = ran.Next(0, 100) });   
            }

            for (int i = 0; i < 100; i++)
            {
                Detail.Details.Add(
                    new DetailModel()
                        {
                            ID = i,
                            Data1 = Guid.NewGuid().ToString().Substring(0, 4),
                            Data2 = Guid.NewGuid().ToString().Substring(0, 4),
                            Data3 = Guid.NewGuid().ToString().Substring(0, 4),
                            Data4 = Guid.NewGuid().ToString().Substring(0, 4),
                            Data5 = Guid.NewGuid().ToString().Substring(0, 4),
                        }); 
            }
        }
    }
bubuko.com,布布扣

添加一个类NavigationControlFrame继承Frame负责控制Navigation, 在这个类里有一个依赖属性CurrentPageObject,在XAML中会将它与ControlViewModel的CurrentPageViewModel绑定,CurrentPageViewMdoel改变时,触发OnCurrentPageObjectChanged。通过XAML里定义的ViewModel类型和Page Uri对应关系找到相应的页面进行切换:

bubuko.com,布布扣
class NavigationControlFrame : Frame
    {
        public NavigationControlFrame()
        {
            Navigated += navigationFrame_Navigated;
        }

        public static readonly DependencyProperty CurrentPageObjectProperty =
            DependencyProperty.Register("CurrentPageObject", typeof(object), typeof(NavigationControlFrame), new PropertyMetadata(default(object), OnCurrentPageObjectChanged));
        
        private static void OnCurrentPageObjectChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            var navigationFrame = (NavigationControlFrame)dependencyObject;
            var newValue = dependencyPropertyChangedEventArgs.NewValue;

            if (newValue == null)
            {
                navigationFrame.Navigate(null);
                return;
            }

            var pageUri = (string)navigationFrame.TryFindResource(newValue.GetType());
            navigationFrame.Navigate(new Uri(pageUri, UriKind.Relative), newValue);
        }

        static void navigationFrame_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            if (e.ExtraData != null)
            {
                var control = e.Content as Page;
                control.DataContext = e.ExtraData;
            }
        }

        public object CurrentPageObject
        {
            get { return GetValue(CurrentPageObjectProperty); }
            set { SetValue(CurrentPageObjectProperty, value); }
        }
    }
bubuko.com,布布扣

 


在XAML中在Resource中定义ViewModel与Page Uri的对应关系,添加NavigtaionControlFrame,并将CurrentPageObject绑定到CurrentPageViewModel,这样ControlViewModel中的CurrentPageViewModel变化时,对应的页面也会进行切换:

bubuko.com,布布扣
<Window x:Class="NavigationApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:navigationApp="clr-namespace:NavigationApp"
        xmlns:viewModels="clr-namespace:ViewModels;assembly=ViewModels"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="600" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.Resources>
            <viewModels:ControlViewModel x:Key="Cvm1"></viewModels:ControlViewModel>
            <sys:String x:Key="{x:Type viewModels:DetailViewModel}">/DetailPage.xaml</sys:String>
            <sys:String x:Key="{x:Type viewModels:SummaryViewModel}">/SummaryPage.xaml</sys:String>
        </Grid.Resources>
        
        <StackPanel Grid.Row="0" Grid.Column="0" DataContext="{StaticResource Cvm1}" Background="LightGreen">
            <navigationApp:NavigationControlFrame CurrentPageObject="{Binding CurrentPageViewModel}">
            </navigationApp:NavigationControlFrame>
            <Button Content="Switch" Command="{Binding SwitchCommand}"></Button>
        </StackPanel>
    </Grid>
</Window>
bubuko.com,布布扣

 

 

WPF: 在MVVM中使用Navigtaion,布布扣,bubuko.com

WPF: 在MVVM中使用Navigtaion

标签:style   blog   class   code   c   java   

原文地址:http://www.cnblogs.com/nofireice/p/3250725.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!