从不同的 ViewModel 访问数据
Accessing data from different ViewModels
我想在单个视图中访问不同 ViewModel 的数据。
但是 DataContext 是完全不同的(MainView 中的 MainViewModel)。是否可以为每个 window 控件设置相应的 ViewModel?
还是仅在 MainViewModel 中创建和引用 ObservableCollection<Student> Students
更好?
目前我想将 ViewModel StudentViewModel
中的 属性 Students
分配给此 ComboBox。
MainViewModel(将 ApplicationViewModel 设置为 CurrentViewModel)
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
CurrentViewModel = ApplicationViewModel;
ShowStudentViewCommand = new RelayCommand(ShowStudentView);
}
public ViewModelBase CurrentViewModel
{
get => _currentViewModel;
set
{
if (_currentViewModel == value) return;
_currentViewModel = value;
RaisePropertyChanged("CurrentViewModel");
}
}
private ViewModelBase _currentViewModel;
private static readonly ApplicationViewModel ApplicationViewModel = new ApplicationViewModel();
private static readonly StudentViewModel StudentViewModel = new StudentViewModel();
public ICommand ShowStudentViewCommand { get; }
public ICommand ShowApplicationViewCommand { get; }
private void ShowStudentView()
{
CurrentViewModel = StudentViewModel;
}
private void ShowApplicationView()
{
CurrentViewModel = ApplicationViewModel;
}
}
ApplicationViewModel 和 StudentViewModel(加载数据并创建 ObservableCollection)
public class ApplicationViewModel : ViewModelBase
{
public ApplicationViewModel()
{
}
}
public class StudentViewModel : ViewModelBase
{
private ObservableCollection<Student> _students;
public StudentViewModel()
{
DataStudentService dataService = new DataStudentService();
Students = new ObservableCollection<Student>(dataService.GetAllStudents());
}
public ObservableCollection<Student> Students
{
get => _students;
private set
{
if (_students == value) return;
_students = value;
RaisePropertyChanged("Students");
}
}
}
MainView.xaml(设置要显示的 CurrentViewModel)
<Window x:Class="Test.View.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Test" Height="750" Width="700"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Grid>
<ContentControl Grid.Row="1" Content="{Binding CurrentViewModel}" />
</Grid>
</Window>
ApplicationView.xaml(目前显示的是这个)
<UserControl x:Class="Test.View.ApplicationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModel="clr-namespace:Test.ViewModel"
mc:Ignorable="d">
<Grid >
<ComboBox
TextSearch.TextPath=""
ItemsSource="{Binding Path=Students}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Path=SelectedStudent, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedIndex="{Binding Path=SelectedStudentIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsSynchronizedWithCurrentItem="True"
IsEditable="True"
Width="200"
Margin="0,0,20,0"
VerticalContentAlignment="Center" />
</Grid>
</UserControl>
最直接的解决方案是坚持 MVVM 模式,方法是创建一个集合并用您已经提到的另一个 class 中的数据填充它。这很容易,每个人都知道发生了什么。此外,这样,数据的 context 将保留在同一视图模型中,并且 - 如果您更改某些内容 - 它也会保留在该上下文中。在您的情况下,这意味着您必须创建一个 ObservableCollection<Student> Students
并将其内容填充到 MainViewModel
.
如果必须从整个应用程序访问该数据,您应该考虑实现 DataManager(例如单例),而不是在每个视图模型中复制数据。
找到解决方案:
MainViewModel
public class MainViewModel : ViewModelBase
{
public StudentViewModel StudentViewModel { get; set; }
public MainViewModel()
{
StudentViewModel = new StudentViewModel();
}
}
主视图
<ComboBox
DataContext="{Binding StudentViewModel}"
ItemsSource="{Binding Path=Students, UpdateSourceTrigger=PropertyChanged}"
/>
StudentViewModel
private ObservableCollection<Student> _students;
public ObservableCollection<Student> Students
{
get => _students;
set
{
if (_students == value) return;
_students = value;
RaisePropertyChanged("Students");
}
}
我想在单个视图中访问不同 ViewModel 的数据。
但是 DataContext 是完全不同的(MainView 中的 MainViewModel)。是否可以为每个 window 控件设置相应的 ViewModel?
还是仅在 MainViewModel 中创建和引用 ObservableCollection<Student> Students
更好?
目前我想将 ViewModel StudentViewModel
中的 属性 Students
分配给此 ComboBox。
MainViewModel(将 ApplicationViewModel 设置为 CurrentViewModel)
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
CurrentViewModel = ApplicationViewModel;
ShowStudentViewCommand = new RelayCommand(ShowStudentView);
}
public ViewModelBase CurrentViewModel
{
get => _currentViewModel;
set
{
if (_currentViewModel == value) return;
_currentViewModel = value;
RaisePropertyChanged("CurrentViewModel");
}
}
private ViewModelBase _currentViewModel;
private static readonly ApplicationViewModel ApplicationViewModel = new ApplicationViewModel();
private static readonly StudentViewModel StudentViewModel = new StudentViewModel();
public ICommand ShowStudentViewCommand { get; }
public ICommand ShowApplicationViewCommand { get; }
private void ShowStudentView()
{
CurrentViewModel = StudentViewModel;
}
private void ShowApplicationView()
{
CurrentViewModel = ApplicationViewModel;
}
}
ApplicationViewModel 和 StudentViewModel(加载数据并创建 ObservableCollection)
public class ApplicationViewModel : ViewModelBase
{
public ApplicationViewModel()
{
}
}
public class StudentViewModel : ViewModelBase
{
private ObservableCollection<Student> _students;
public StudentViewModel()
{
DataStudentService dataService = new DataStudentService();
Students = new ObservableCollection<Student>(dataService.GetAllStudents());
}
public ObservableCollection<Student> Students
{
get => _students;
private set
{
if (_students == value) return;
_students = value;
RaisePropertyChanged("Students");
}
}
}
MainView.xaml(设置要显示的 CurrentViewModel)
<Window x:Class="Test.View.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Test" Height="750" Width="700"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Grid>
<ContentControl Grid.Row="1" Content="{Binding CurrentViewModel}" />
</Grid>
</Window>
ApplicationView.xaml(目前显示的是这个)
<UserControl x:Class="Test.View.ApplicationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModel="clr-namespace:Test.ViewModel"
mc:Ignorable="d">
<Grid >
<ComboBox
TextSearch.TextPath=""
ItemsSource="{Binding Path=Students}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Path=SelectedStudent, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedIndex="{Binding Path=SelectedStudentIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsSynchronizedWithCurrentItem="True"
IsEditable="True"
Width="200"
Margin="0,0,20,0"
VerticalContentAlignment="Center" />
</Grid>
</UserControl>
最直接的解决方案是坚持 MVVM 模式,方法是创建一个集合并用您已经提到的另一个 class 中的数据填充它。这很容易,每个人都知道发生了什么。此外,这样,数据的 context 将保留在同一视图模型中,并且 - 如果您更改某些内容 - 它也会保留在该上下文中。在您的情况下,这意味着您必须创建一个 ObservableCollection<Student> Students
并将其内容填充到 MainViewModel
.
如果必须从整个应用程序访问该数据,您应该考虑实现 DataManager(例如单例),而不是在每个视图模型中复制数据。
找到解决方案:
MainViewModel
public class MainViewModel : ViewModelBase
{
public StudentViewModel StudentViewModel { get; set; }
public MainViewModel()
{
StudentViewModel = new StudentViewModel();
}
}
主视图
<ComboBox
DataContext="{Binding StudentViewModel}"
ItemsSource="{Binding Path=Students, UpdateSourceTrigger=PropertyChanged}"
/>
StudentViewModel
private ObservableCollection<Student> _students;
public ObservableCollection<Student> Students
{
get => _students;
set
{
if (_students == value) return;
_students = value;
RaisePropertyChanged("Students");
}
}