如何从弹出窗口

时间:2016-07-13 01:48:34

标签: c# wpf xaml mvvm

我正在尝试学习MVVM,但我发现这是一个噩梦,试图了解如何在使用MVVM的应用程序中正确导航视图之间。经过一段时间研究和尝试理解不同的技术后,我遇到了Rachel Lim's blog的方法。此技术将ViewModel用于应用程序本身,并跟踪应用程序状态,例如当前页面。我觉得这对我的申请来说是一个很好的方法。

现在转移到我的问题..

我想要实现的目标

我想要一个具有一个主应用程序视图的应用程序,该视图将LoginView和HomeView存储为DataTemplates,并具有一个内容控件,将LoginView设置为应用程序启动时显示的视图。 LoginView将有一个按钮,按下该按钮将打开另一个有按钮的窗口。当按下弹出窗口中的按钮时,我想将主应用程序窗口中的视图从LoginView更改为HomeView。

到目前为止我有什么

我有一个设置ApplicationView的工作正常。

<Window x:Class="WPF_Navigation_Practice.Views.ApplicationView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:ignore="http://www.galasoft.ch/ignore"
        xmlns:vm="clr-namespace:WPF_Navigation_Practice.ViewModels"
        xmlns:views="clr-namespace:WPF_Navigation_Practice.Views"
        mc:Ignorable="d ignore"
        DataContext="{StaticResource ApplicationViewModel}">

    <Window.Resources>
        <DataTemplate DataType="{x:Type vm:LoginViewModel}">
            <views:LoginView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:HomeViewModel}">
            <views:HomeView />
        </DataTemplate>
    </Window.Resources>

    <Grid>
        <ContentControl Content="{Binding CurrentPageViewModel}" />
    </Grid>
</Window>

并按如下方式设置了ApplicationViewModel。将当前页面设置为LoginViewModel。

using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using WPF_Navigation_Practice.Interfaces;

namespace WPF_Navigation_Practice.ViewModels
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class ApplicationViewModel : ViewModelBase
    {
        #region Fields

        private ICommand _changePageCommand;

        private IPageViewModel _currentPageViewModel;
        private List<IPageViewModel> _pageViewModels;

        #endregion

        public ApplicationViewModel()
        {
            // Add available pages
            PageViewModels.Add(new LoginViewModel());
            PageViewModels.Add(new HomeViewModel());
            PageViewModels.Add(new CodeViewModel());


            // Set starting page
            CurrentPageViewModel = PageViewModels[0];
        }

        #region Properties / Commands

        public ICommand ChangePageCommand
        {
            get
            {
                if (_changePageCommand == null)
                {
                    _changePageCommand = new RelayCommand<object>(
                        p => ChangeViewModel((IPageViewModel)p),
                        p => p is IPageViewModel);
                }

                return _changePageCommand;
            }
        }

        public List<IPageViewModel> PageViewModels
        {
            get
            {
                if (_pageViewModels == null)
                    _pageViewModels = new List<IPageViewModel>();

                return _pageViewModels;
            }
        }

        public IPageViewModel CurrentPageViewModel
        {
            get
            {
                return _currentPageViewModel;
            }
            set
            {
                if (_currentPageViewModel != value)
                {
                    _currentPageViewModel = value;
                    RaisePropertyChanged("CurrentPageViewModel");
                }
            }
        }


        #endregion

        #region Methods

        private void ChangeViewModel(IPageViewModel viewModel)
        {
            if (!PageViewModels.Contains(viewModel))
                PageViewModels.Add(viewModel);

            CurrentPageViewModel = PageViewModels
                .FirstOrDefault(vm => vm == viewModel);
        }

        #endregion
    }
}

当我运行应用程序时,它将显示我的主应用程序窗口,该窗口显示loginView,它是一个UserControl,并被设置为带有ContentPresenter的currentPageViewModel。

单击LoginView UserControl中的按钮时,将打开另一个窗口。如下图所示。

enter image description here

这是该窗口的XAML。

<Window x:Class="WPF_Navigation_Practice.Views.CodeView"
    x:Name="CodeWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ignore="http://www.galasoft.ch/ignore"
    xmlns:z="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:viewModels="clr-namespace:WPF_Navigation_Practice.ViewModels"
    mc:Ignorable="d ignore"
    d:DesignWidth="623.224" d:DesignHeight="381.269"
    DataContext="{Binding CodeViewModel, Source={StaticResource ApplicationViewModel}}">

<Grid>
    <Button Content="Ok" 
            HorizontalAlignment="Left" 
            Margin="235,166,0,0" 
            VerticalAlignment="Top"
            Width="138" 
            FontSize="20" 
            Height="67"/>
    <Label Content="Second Window" HorizontalAlignment="Left" Margin="166,56,0,0" VerticalAlignment="Top" FontSize="36"/>
</Grid>

我的问题

我想要实现的是当单击第二个视图窗口中的“确定”按钮时,我想从LoginView更改ApplicationView窗口中的currentPageViewModel以显示HomeView,但我对如何实现此目标感到困惑。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

我看到你已经在使用MVVMLight了。有一个Messenger课程可以帮助你。在ApplicationViewModel构造函数中注册到messenger,在处理按钮的代码中单击CodeViewModel,使用Send发送消息。在传递给注册的操作中,根据需要更改视图模型。

参见http://www.mvvmlight.net/help/WP8/html/9fb9c53a-943a-11d7-9517-c550440c3664.htmUse MVVM Light's Messenger to Pass Values Between View Model

我没有MVVMLight给你写一个示例代码。我从头开始写了一个ViewModelMessenger,我的是这样的:

public static void Register(string actionName, object registerer, Action<object, object> action)
{
    var actionKey = new Tuple<string, object>(actionName, registerer);
    if (!RegisteredActions.ContainsKey(actionKey))
    {
        RegisteredActions.Add(actionKey, action);
    }
    else
    {
        RegisteredActions[actionKey] = action;
    }
}

用过:

VMMessenger.Register("ChangeViewModel",this,ChangeViewModelAction)

public static void SendMessage(string messageName, object message, object sender)
{
    var actionKeys = RegisteredActions.Keys.ToList();
    foreach (Tuple<string, object> actionKey in actionKeys)
    {
        if (actionKey.Item1 == messageName)
        {
            Action<object, object> action;
            if (RegisteredActions.TryGetValue(actionKey, out action))
            {
                action?.Invoke(message, sender);
            }
        }
    }
}

用过:

VMMessenger.SendMessage("ChangeViewModel","HomeViewModel",this);

并在ChangeViewModelAction中,您可以检查ViewModel名称并将CurrentPageViewModel更改为具有匹配名称的名称。