如何使用 DataTemplates 通过 ViewModel-First 方法缓存动态切换的视图 [英] How to cache dynamically switched views by ViewModel-First approach using DataTemplates

查看:32
本文介绍了如何使用 DataTemplates 通过 ViewModel-First 方法缓存动态切换的视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(我使用的是 GalaSoft.MvvmLight 框架)

(I am using GalaSoft.MvvmLight framework)

我的 MainWindow.xaml 中有一些视图,我在运行时通过用户选择在它们之间动态切换.

I have some views in my MainWindow.xaml that I am switching between them dynamically in run-time, by user selection.

这些视图使用以下技术与其对应的视图模型绑定:

These views using the following technique to bind with their corresponding view-model:

MainWindow.xaml

...
<Window.Resources>
        <DataTemplate DataType="{x:Type vm:Control1ViewModel}">
            <v:Control1/>
        </DataTemplate>
    ... // Assume there is more then one DataTemplate. Every view has a unique view-model.
</Window.Resources>
...

Control1ViewModel.cs

public class Control1ViewModel : ViewModelBase
{
    ...
}

MainWindow.xaml 使用以下技术在上述视图之间切换:

The MainWindow.xaml using the following technique to switch between the above views:

MainWindow.xaml

...
<ContentControl Content="{Binding CurrentView}"/> // This is were the view appears.
...

MainViewModel.cs

public class MainViewModel : ViewModelBase
{
    ...
    private ViewModelBase _currentView;
    public ViewModelBase CurrentView
    {
        get { return _currentView; }
        private set
        {
            _currentView = value;
            base.RaisePropertyChanged("CurrentView");
        }
    }
    ...
}

为了方便起见,我没有添加更多控件,只是放了一个(Control1)来缩短问题代码部分.如上所述,假设要切换的视图不止一种.

For your convenience, I didn't add more controls, just put one (Control1) to shorten the question code section. As mentioned above, Assume there is more then one view to switch.

Everytime CurrentView 属性设置为新的 ViewModelBase 值(例如 Control1ViewModel),WPF将构造绑定视图的新实例DataTemplate 可视化树对象,因此旧的将丢失.

Everytime the CurrentView property set with a new ViewModelBase value (e.g. Control1ViewModel), WPF will construct a new instance of the binded view DataTemplate visual tree object, so the old one will be lost.

这意味着我无法在它们之间切换时缓存视图(例如 Control1).

That means I cannot cache the views (e.g. Control1) while switching between them.

我找到的唯一解决方案是使用其 ViewModel(使用 DataContext)对视图进行硬编码",但按照此解决方案,会发生以下情况:

The only solution I had found to my answer was to "hardcode" the View with its ViewModel (using DataContext), but following this solution the bellow happens:

  • 我打破了 ViewModel-First 方法.
  • 为了不破坏完整的 MVVM,我必须更改 CurrentView 签名并将其移动到我的 MainWindow.xaml 后面的代码中.
  • 我没有切换 ViewModelBase 类型,而是切换具体控件.
  • I am breaking the ViewModel-First approach.
  • In order not to break the complete MVVM, I have to change CurrentView signature and move it to the code behind of my MainWindow.xaml.
  • Instead of switching ViewModelBase types, I am switching concrete controls.

我想知道是否有任何解决方案不使用视图模型对视图进行硬编码",这样我就可以保留当前的 ​​ViewModelBase 开关和 ViewModel-First 方法.

I would like to know if there is any solution without "hardcoding" the view with view-model, so I can keep the current ViewModelBase switch and the ViewModel-First approach.

推荐答案

你可以有以下方法:

  1. 代替 ContentControl 取一个 ItemsControl

  1. ItemsControlItemsPanel 作为网格,对于 SelectedItemZ-Index 设置为1 和其余的 Items 将 Z-Index 设置为 0.这样,一次只能看到一个视图,而该视图将覆盖其他视图.

  1. Take ItemsPanel of the ItemsControl as a Grid and for SelectedItem set Z-Index to 1 and for rest of the Items set Z-Index to 0. In this way only one view would be visible at a time which will be over the other views.

MainViewModel 中取两个属性.Views 类型 ObservableCollectionCurrentView 类型 ViewModelBase 并将其与 ItemsControls<绑定/code> 的 ItemsSourceSelectedItem 分别.

Take two properties in the MainViewModel. Views of type ObservableCollection<ViewModelBase> and CurrentView of type ViewModelBase and bind it with the ItemsControls's ItemsSource and SelectedItem respectively.

现在当你想打开一个视图时,创建一个 ViewModel,将它添加到 Views 列表并将其设置为 CurrentView.如果它已经在列表中,只需将其设置为CurrentView.

Now when you want to open a view, create a ViewModel, add it to Views list and set it a CurrentView. If it is already there in the list, just set it asCurrentView.

如果您希望它永远关闭,还可以提供一个关闭按钮.即如果您将其关闭,它将从列表中删除并且不会被缓存.

Also provide a close button if you want it to be closed forever. i.e. if you will close it, it will be removed from the list and won't be cached.

这就像您在窗口中打开了不同的视图并且可以在它们之间切换一样工作.如果需要,您可以关闭视图.

This would work as if you have different views opened in your window and you can switch between them. And if you want you can close a view.

见下面的代码:

            <ItemsControl ItemsSource="{Binding Views}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Grid Margin="10,10,0,10">
                        </Grid>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>

                <ItemsControl.ItemContainerStyle>
                    <Style>
                        <Setter Property="Grid.Opacity" Value="{Binding ZIndex}"/>
                        <Setter Property="Grid.ZIndex" Value="{Binding ZIndex}"/>
                    </Style>
                </ItemsControl.ItemContainerStyle>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <ContentControl Content="{Binding}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>

在这里您可以看到,在您的 ViewModel 中,您必须有一个属性 ZIndex,它将用于在顶部显示当前视图.所以每当你想显示视图时,只需将 ViewModelZIndex 属性设置为 1 并将重置视图重置为 0.

Here you can see that in your ViewModel you will have to have a property ZIndex, which will be used to show the current view on the top. So whenever you want to show view, just set ZIndex property of ViewModel to 1 and reset reset view to 0.

这篇关于如何使用 DataTemplates 通过 ViewModel-First 方法缓存动态切换的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆