Существуют различные фреймворки, такие как Prism , Caliburn Micro , MVVMLight и многие другие, которые предоставляют функции для написания приложения шаблона проектирования MVVM. Немного из функций, которые предоставляют упомянутые рамки
- DelegateCommand или RelayCommand
- ViewModelLocator
- Контейнер / Модуль
- Агрегатор событий
Эти функции упрощают написание кода в шаблоне проектирования MVVM. Однако, если вам не нужны все эти функции и вы не хотите их интегрировать, не беспокойтесь об этом.
Теперь все разговоры в этом ответе основаны на том, что вы хотите написать для своей реализации без этих каркасов.
Вы можете обратиться к этому блогу, чтобы написать RelayCommand . Вам требуется реализация ICommand
, если вы хотите отделить View от ViewModel. Эти команды ViewModel могут быть интегрированы с View с использованием триггера Blends 'Interacctivity (см. sample ).
Все вышеизложенное было подготовкой к решению вашего вопроса. Следуйте инструкциям
- Создание ViewModel
В представленной ниже модели ViewModel показано, что вам требуется:
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<Issue> issues = new ObservableCollection<Issue>();
public ObservableCollection<Issue> Issues { get {return issues;} }
private ObservableCollection<string> users = new ObservableCollection<string>();
public ObservableCollection<string> Users { get {return users;} }
private string user;
public string User
{
get
{
return user;
}
set
{
user = value;
NotifyPropertyChanged();
}
}
private ICommand userChangedCommand;
public ICommand UserChangedCommand
{
get
{
return userChangedCommand ?? (userChangedCommand = new RelayCommand(
x =>
{
OnUserChanged();
}));
}
}
private ICommand loadedCommand;
public ICommand LoadedCommand
{
get
{
return loadedCommand?? (loadedCommand= new RelayCommand(
x =>
{
// Write Code here to populate Users collection.
}));
}
}
private void OnUserChanged()
{
Issues.Clear();
string name = this.User;
Issues fetchedIssues = new Issues();
var issuesList = fetchedIssues.FetchIssues(name); // returns the list of Issues in a type of --> IQueryable<Issue>
foreach (var issue in issuesList)
{
Issues.Add(issue);
}
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
2. Просмотреть изменения:
<Controls:MetroWindow x:Name="Main_Window" x:Class="Dull.MainWindow" ........
>
<i:EventTrigger EventName="Loaded" >
<i:InvokeCommandAction Command="{Binding LoadedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Controls:MetroWindow.RightWindowCommands>
<Controls:WindowCommands>
<ComboBox x:Name="Name" ItemsSource="{Binding Users}" SelectionChanged="OnNameComboChanged" SelectedItem="{Binding User}" > <!-- Combox box is getting user details from ViewModel -->
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged" >
<i:InvokeCommandAction Command="{Binding UserChangedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</Controls:WindowCommands>
</Controls:MetroWindow.RightWindowCommands>
<Grid>
<ListView x:Name="issuesListView" ItemsSource="{Binding Issues}"> <!-- ListView binded to Issues collection -->
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Summary}"
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
3. Теперь последняя часть Как Привязать ViewModel к представлению .
Если вы используете упомянутые фреймворки, то это будет тривиально на основе функции ViewModelLocator
. Тем не менее, чтобы достичь без рамок, вы можете использовать один из следующих подходов.
1) Создайте экземпляр ViewModel и назначьте его в методе InitializeComponent элемента управления (.Xaml.cs)
var vm = new MyViewModel();
this.DataContext = vm;
Однако это нарушает чистый шаблон проектирования MVVM
2) Вы можете создать экземпляр в самом представлении
<Controls:MetroWindow x:Name="Main_Window" x:Class="Dull.MainWindow">
<Controls:MetroWindow.DataContext>
<VM:MyViewModel />
</Controls:MetroWindow.DataContext>
...............
</Controls:MetroWindow>