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
相关产品推荐
相关产品推荐

