You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF MVVM框架下页面导航传值及返回数据状态问题咨询

WPF MVVM导航与状态保持解决方案

一、替换静态实例的导航方式(符合MVVM规范)

直接通过MainWindow.Instance访问视图元素属于紧密耦合的写法,违反MVVM关注点分离原则,既不利于单元测试,也降低了代码扩展性。推荐使用抽象导航服务的方式实现解耦:

1. 定义导航服务接口

public interface INavigationService
{
    void NavigateTo(Type viewType, object parameter = null);
    void GoBack();
}

2. 在MainWindow中实现导航服务

public class MainNavigationService : INavigationService
{
    private readonly Frame _mainFrame;
    private readonly Dictionary<Type, object> _viewCache = new(); // 视图实例缓存,用于保持状态

    public MainNavigationService(Frame mainFrame)
    {
        _mainFrame = mainFrame;
        // 初始化默认导航到Home页
        NavigateTo(typeof(Home));
    }

    public void NavigateTo(Type viewType, object parameter = null)
    {
        // 优先复用缓存的视图实例
        if (_viewCache.TryGetValue(viewType, out var cachedView))
        {
            _mainFrame.Navigate(cachedView, parameter);
        }
        else
        {
            var newView = Activator.CreateInstance(viewType);
            _viewCache.Add(viewType, newView);
            _mainFrame.Navigate(newView, parameter);
        }
    }

    public void GoBack()
    {
        if (_mainFrame.CanGoBack)
            _mainFrame.GoBack();
    }
}

3. 注入导航服务到ViewModel

在MainWindow.xaml.cs中初始化服务并传递给HomeViewModel:

public MainWindow()
{
    InitializeComponent();
    var navigationService = new MainNavigationService(Main);
    var homeViewModel = new HomeViewModel(navigationService);
    // 假设Home页是Frame的初始内容,直接设置DataContext
    if (Main.Content is Home homePage)
    {
        homePage.DataContext = homeViewModel;
    }
}

二、实现StoreDetailCommand与数据传递

1. 完善HomeViewModel

假设已实现INotifyPropertyChanged,补充选中项绑定和命令逻辑:

public class HomeViewModel : INotifyPropertyChanged
{
    private readonly INavigationService _navigationService;
    private Store _selectedStore;

    public ObservableCollection<Store> ListStore { get; } = new();
    public Store SelectedStore
    {
        get => _selectedStore;
        set
        {
            _selectedStore = value;
            OnPropertyChanged(nameof(SelectedStore));
        }
    }
    public ICommand StoreDetailCommand { get; }

    public HomeViewModel(INavigationService navigationService)
    {
        _navigationService = navigationService;
        StoreDetailCommand = new RelayCommand(displayStoreDetail);
        // 初始化ListStore数据逻辑...
    }

    private void displayStoreDetail()
    {
        if (SelectedStore == null) return;
        // 导航到详情页并传递选中的商店数据
        _navigationService.NavigateTo(typeof(StoreDetail), SelectedStore);
    }

    // INotifyPropertyChanged实现代码...
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 在StoreDetail页接收数据

在StoreDetail.xaml.cs中获取导航参数并传递给ViewModel:

public StoreDetail()
{
    InitializeComponent();
    Loaded += StoreDetail_Loaded;
}

private void StoreDetail_Loaded(object sender, RoutedEventArgs e)
{
    if (DataContext is StoreDetailViewModel vm && NavigationService?.ExtraData is Store selectedStore)
    {
        vm.SelectedStore = selectedStore;
    }
}

三、保持Home页的数据状态

通过MainNavigationService中的_viewCache字典,我们会缓存Home页的实例,每次返回时复用该实例而非创建新对象,这样ListStore的选中状态、数据内容都会自动保留。如果需要更细粒度的状态控制,也可以将HomeViewModel的实例进行缓存,确保ViewModel不被重建。

内容的提问来源于stack exchange,提问作者Kayyy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 11:35:28