Доступ к данным из разных ViewModels - PullRequest
0 голосов
/ 22 февраля 2019

Я хотел бы получить доступ к данным разных ViewModels в одном представлении.Но DataContext является совершенно другим (MainViewModel в MainView).Можно ли установить соответствующую ViewModel для каждого элемента управления окна?Или лучше создать и ссылаться на ObservableCollection<Student> Students только в MainViewModel?

В данный момент я хотел бы назначить свойство Students из ViewModel StudentViewModel для этого 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>

Ответы [ 2 ]

0 голосов
/ 23 февраля 2019

Нашли решение:

MainViewModel

public class MainViewModel : ViewModelBase
{
    public StudentViewModel StudentViewModel { get; set; }

    public MainViewModel()
    {
        StudentViewModel = new StudentViewModel();
    }
}

MainView

<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");
            }
        }
0 голосов
/ 22 февраля 2019

Самым простым решением было бы придерживаться шаблона MVVM, создав коллекцию и наполнив ее данными из другого класса, как вы уже упоминали.Это легко, и все знают, что происходит.Кроме того, таким образом контекст данных остается в той же модели представления и - если вы что-то меняете - он также остается в этом контексте.В вашем случае это означает, что вы должны создать ObservableCollection<Student> Students и заполнить его содержимое в MainViewModel.


Если к этим данным нужно обращаться со всего вашего приложения, вам следует подумать о реализацииDataManager (например, одиночный), а не копировать данные в каждой модели представления.

...