我有主窗口中的内容控制和两个收音机按钮loceted. MainWindow.xaml:
<Grid>
<StackPanel >
<RadioButton Content="First"
IsChecked="True"
Command="{Binding FirstViewCommand}"/>
<RadioButton Content="Second"
Command="{Binding SecondViewCommand}"/>
</StackPanel>
<ContentControl Grid.Row="1"
Grid.Column="1"
Content="{Binding CurrentView}"/>
</Grid>
字符串
我绑定我的用户控件到这个内容控件。这里我有组合框列表框和按钮。基于Cobobox.SelectedElement我需要在按下按钮后更改列表框中的数据。用户控件:
<Grid>
<ComboBox x:Name="BoxOfDetails"
ItemsSource="{Binding DetailsScheme}">
</ComboBox>
<Button Command="{Binding ProduceCommand}"
CommandParameter="{Binding ElementName=BoxOfDetails, Path=SelectedItem}" />
<ListBox x:Name="ListOfMaterials"
ItemsSource="{Binding Materials}" >
</ListBox>
</Grid>
型
我还有主视图模型,它是主窗口的数据上下文:
class MainVM : ObservableObject
{
public RelayCommand FirstViewCommand { get; set; }
public RelayCommand SecondViewCommand { get; set; }
public FirstVM FirstViewModel { get; set; }
public SecondVM SecondViewModel { get; set; }
private object _currentView;
public object CurrentView
{
get { return _currentView; }
set => Set(ref _currentView, value);
}
public MainVM()
{
FirstViewModel = new FirstVM();
SecondViewModel = new SecondVM();
CurrentView = FirstViewModel;
FirstViewCommand = new RelayCommand(o =>
{
CurrentView = FirstViewModel;
});
SecondViewCommand = new RelayCommand(o =>
{
CurrentView = SecondViewModel;
});
}
型
我的用户控件的视图模型:
class FirstVM : ObservableObject
{
private ObservableCollection<DetailScheme> _detailsScheme;
private ObservableCollection<Material> _materials;
public ObservableCollection<DetailScheme> DetailsScheme
{
get => _detailsScheme;
public ObservableCollection<Material> Materials
{
get => _materials;
set => Set(ref _materials, value);
}
public RelayCommand ProduceCommand { get; set; }
public FirstVM ()
{
_detailsScheme = GetDetailsScheme("D:/ DetailsScheme.json");
_materials = GetMaterials("D:/ Materials.json");
ProduceCommand = new RelayCommand(o =>
{***});
}
型
我需要保存在我的列表框中的信息时,我的用户控制切换(例如,用户选择框中的东西,并按下一个按钮,列表框中的数据正在更新后,现在切换控制我有相同的信息,因为它是当我启动应用程序)
我在我的用户控件视图模型中添加了将信息保存到文件的方法:
public void SaveFirstVM()
{
SaveDetails(_details, "D:/ Details.json");
SaveMaterials(_materials, "D:/ Materials.json");
}
型
当我在主视图模型中切换视图时,
SecondViewCommand = new RelayCommand(o =>
{
CurrentView = SecondViewModel;
FirstViewModel.SaveFirstVM()
});
型
但是什么也没有发生,我可以在每次按下UserControl View Model中的produce按钮后调用这个保存方法,但是我不认为这是一个好方法。我在我的项目中添加了一些断点,我只能建议问题是我的UserControl View Model创建了两次,第一次在MainVM中,第二次在初始化发生时,当我更改数据时,它发生在初始化的对象中,当我试图从mainVM保存数据时,它保存了其他未更改的对象
2条答案
按热度按时间ca1c2owp1#
你已经用“MVVM”标记了你的问题,但你没有实现它。在MVVM中,你有负责数据持久化的 Model。MVVM并不意味着把所有东西都压缩到 View Model 类中。拥有一个带有 Model 类的 Model 应该会让流程更明显。
您可以处理
Frameworkelement.Unloaded
事件以获得有关当前视图正在卸载的通知。然而,优雅的解决方案是管理与页面相关的持久性,您已经完全控制了页面管理:您的MainVM
类。代码应该是内聚的,类似或相关的任务不应该分散在应用程序中。
MainVM
已经能够精确地识别页面切换,而无需额外的努力。由于MainVM
应该引用一个或多个 Model 类,以便获取它将暴露给视图的数据,例如通过初始化页面视图模型类,它也能够调用相关的模型类进行持久化。请注意,在正确的干净的OO编程中,你必须关心类型和类型成员的可访问性(访问修饰符,如
public
或private
)。这是一个非常基本的技术,可以使你的代码健壮,API定义良好。不要将所有内容都设置为
public
。相反,将所有内容设置为private
,并仅在必要时将其更改为限制较少的可见性,例如public
。这还包括属性访问器。例如,声明private set;
和公共get;
。类内部必须仅对定义类或子类可见。请参阅数据隐藏。修复/改进的代码(包括正确的MVVM结构和访问修饰符用法)如下所示:
PageId.cs
字符串
MainVM.cs
型
使用
MainVM.NextPageCommand
如下:型
实现持久化细节的 Model 类:
仓库.cs
型
JsonRepository.cs
型
wko9yo5t2#
我使用一个名为
ObservableHandler<T>
的类,它让我可以监视另一个实现INotifyPropertyChanged
并侦听PropertyChanged
事件的类。如果你要使用它,你可以在另一个ViewModel中观察属性的变化,而不必保存到文件中。
用法
字符串
Observable可观察性
型