子ViewModel应该能够在Parent ViewModel上更改吗?

时间:2017-04-23 15:13:33

标签: c# wpf mvvm

我有一个情况,我不确定我是否正确。

我的ApplicationViewModel是我整个应用程序的“shell”。

在该视图模型中,我有其他子视图模型。

    public ApplicationModelView()
    {
        ModelViewPages.Add(new GameViewModel());
        ModelViewPages.Add(new EditGameViewModel());
        //Set Current HomePage
        CurrentPage = ModelViewPages[0];
    }
    #endregion

    #region Properties
    public BaseModelView CurrentPage
    {
        get { return _currentPage; }
        set { _currentPage = value; OnPropertyChanged(); }
    }
    public List<BaseModelView> ModelViewPages
    {
        get
        {
            if (_modelViewPages == null){_modelViewPages = new List<BaseModelView>();}
            return _modelViewPages;
        }                        
    }
    #endregion

在我的GameViewModel中,我会显示模型GamesModel中包含标题,说明等的对象列表。

当我点击此列表中的某个项目时,它会被选中,然后我想用一个按钮将我的视图更改为EditGameViewModel,但我不确定该怎么做。

如何让我的child-ViewModel更改我的父ViewModel中的内容? 或者孩子应该这样做吗?

修改

How I want it to function

我想选择一个项目,然后点击我从视图GameViewModel更改为EditGameViewModel的按钮,其中包含我从列表中选择的数据。

 public void EditGame(object param)
    {
        //MessageBox.Show("From EditGame Function"); HERE I WANT TO CHANGE THE VIEWMODEL ON MY APPLICATIONVIEWMODEL
    }
    public bool CanEditGame(object param)
    {            
        return SelectedGame != null;
    }

1 个答案:

答案 0 :(得分:0)

我可以提供有用的东西,但可能会有问题。这一切都取决于您计划如何运行应用程序。

首先,类似于你的MainViewModel,你需要这样的东西:

public class MainViewModel : ObservableObject //ObservableObject being a property change notification parent
{
    //Current view will always be here
    public BaseViewModel ViewModel { get; set; }

    public MainViewModel()
    {
        //By default we will say this is out startup view
        Navigate<RedViewModel>(new RedViewModel(this));
    }

    public void Navigate<T>(BaseViewModel viewModel) where T : BaseViewModel
    {
        ViewModel = viewModel as T;
        Console.WriteLine(ViewModel.GetType());
        OnPropertyChanged("ViewModel");
    }
}

现在,由于我们以这种方式导航,因此每个子视图都需要从BaseViewModel派生。

public class BaseViewModel : ObservableObject
{
    private MainViewModel _mainVM;

    public BaseViewModel(MainViewModel mainVM)
    {
        _mainVM = mainVM;
    }

    protected void Navigate<T>() where T : BaseViewModel
    {
        //Create new instance of generic type(i.e. Type of view model passed)
        T newVM = (T)Activator.CreateInstance(typeof(T), _mainVM);
        //Change MainViewModels ViewModel to the new instance
        _mainVM.Navigate<T>(newVM);
    }
}

现在我们真的需要看看我们将如何让子视图委托这一变化。所以我们将有一个BlueView。

public class BlueViewModel : BaseViewModel
{
    //Relay command to call 'ToRed' function
    public ICommand ChangeToRed
    {
        get { return new RelayCommand(ToRed); }
    }

    //Requires MainViewModel for BaseViewModel
    public BlueViewModel(MainViewModel main) : base(main)
    {

    }

    //Calling BaseViewModel function. Passed BaseViewModel Type
    public void ToRed(object param)
    {
        Navigate<RedViewModel>();
    }
}

和RedView:

public class RedViewModel : BaseViewModel
{
    //Relay command to call 'ToBlue' function
    public ICommand ChangeToBlue
    {
        get { return new RelayCommand(ToBlue); }
    }

    //Requires MainViewModel for BaseViewModel
    public RedViewModel(MainViewModel main) : base(main)
    {

    }

    //Calling BaseViewModel function. Passed BaseViewModel Type
    public void ToBlue(object param)
    {
        Navigate<BlueViewModel>();
    }
}

我们的MainWindow.xaml可能如下所示:

<Window.DataContext>
    <viewmodels:MainViewModel/>
</Window.DataContext>

<Grid>
    <ContentControl Content="{Binding ViewModel}" />
</Grid>

这样做,所有孩子都可以打电话给他们的父母他们想要改变。 BaseViewModel为所有派生的孩子保留这个父级,因此他们可以像导弹一样在导航期间来回传递它。

同样,导航完全取决于您如何使用,构建和规划您的应用程序。它并不总是一刀切。