Вокруг целого rnet есть тонны и тонны статей об этой топике c, но я просто не могу обернуть ее вокруг. Большинство статей используют код позади, но я хочу придерживаться «чистого» MVVM, так как я пытаюсь изучить его. Кроме того, я явно не хочу использовать какой-либо другой фреймворк (MVVMlight, Ninject ...). Я просто хочу придерживаться того, что может предложить WPF. Я знаю, что об этом часто спрашивают, но я не нашел mvvm или не указал c достаточно.
Моя задача проста: я хочу увидеть самое простое решение открытия модального диалога, отправьте ему строку и получите строку из диалогового окна после ее закрытия.
Поэтому я настроил свой MainWindow.xaml с полем ввода текста (TextBox), кнопкой (которая должна открыть модальное диалоговое окно) и текстовый блок, который покажет сообщение, которое я намерен получить из диалогового окна.
В диалоговом окне есть TextBlock, показывающий вводимые пользователем данные из MainWindow.xaml, а также TextBox для ввода некоторого текста и кнопку. Вы догадались: вы нажимаете кнопку, и сообщение, которое я набрал в текстовом поле get, возвращается в MainWindow.xaml. Пожалуйста, обратитесь также к изображениям, которые я включил - я думаю, что это довольно очевидно.
MainWindow.xaml
<Window x:Class="Dialogs.MainWindow"
...
Title="First View (Main Window)" Height="240" Width="630">
<Grid>
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="10">
<TextBlock Text="Main View sayz: "/>
<TextBox Width="360" Margin="10,0,0,30"/>
</StackPanel>
<Button Content="Send to Second View" Command="{Binding SendToSecondViewCommand}" Width="200"/>
<StackPanel Orientation="Horizontal" Margin="10,30,10,10">
<TextBlock Text="Second View replies: "/>
<TextBlock Width="360"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
SecondView.xaml
<UserControl x:Class="Dialogs.SecondView"
...
d:DesignHeight="240" d:DesignWidth="630" Background="BlanchedAlmond">
<Grid>
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="10">
<TextBlock Text="This is what First View sayz: "/>
<TextBlock Width="360"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10">
<TextBlock Text="Second View replies: "/>
<TextBox Width="360" Margin="10,0,0,30"/>
</StackPanel>
<Button Content="Reply to First View" Command="{Binding ReplyToFirstViewCommand}" Width="200"/>
</StackPanel>
</Grid>
</UserControl>
Здесь Вот как я реализовал INotifyPropertyChanged (Это на самом деле файл .cs с именем BaseClasses; я знаю, что он не назван правильно ...)
public abstract class NotifyPropertyChangedBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged<T>(ref T variable, T value,
[CallerMemberName] string propertyName = null)
{
variable = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
А вот мой базовый класс для команд реле:
public class CommandDelegateBase : ICommand
{
public delegate void ExecuteDelegate(object parameter);
public delegate bool CanExecuteDelegate(object paramerter);
private ExecuteDelegate execute;
private CanExecuteDelegate canExecute;
public CommandDelegateBase(ExecuteDelegate _execute, CanExecuteDelegate _canExecute = null)
{
execute = _execute;
canExecute = _canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return canExecute?.Invoke(parameter) ?? true;
}
public void Execute(object parameter)
{
execute.Invoke(parameter);
}
}
Наконец, мои ViewModels: FirstViewModel:
public class FirstViewViewModel: NotifyPropertyChangedBase
{
private string _sendText;
public string SendText
{
get { return _sendText; }
set
{
_sendText = value;
OnPropertyChanged(ref _sendText, value);
}
}
public ICommand SendToSecondViewCommand { get; set; }
public FirstViewViewModel()
{
SendToSecondViewCommand = new CommandDelegateBase(SendExecuteCommand, SendCanExecuteCommand);
}
private bool SendCanExecuteCommand(object paramerter)
{
return true;
}
private void SendExecuteCommand(object parameter)
{
//Do stuff to :
// a) show the second view as modal dialog
// b) submit what I just wrote (SendText)
}
}
SecondViewModel:
public class SecondViewViewModel : NotifyPropertyChangedBase
{
private string _replyText;
public string ReplyText
{
get { return _replyText; }
set
{
_replyText = value;
OnPropertyChanged(ref _replyText, value);
}
}
public ICommand ReplyToFirstViewCommand { get; set; }
public SecondViewViewModel()
{
ReplyToFirstViewCommand = new CommandDelegateBase(ReplyExecuteCommand, ReplyCanExecuteCommand);
}
private bool ReplyCanExecuteCommand(object paramerter)
{
return true;
}
private void ReplyExecuteCommand(object parameter)
{
//Do stuff to :
// a) close the second view
// b) reply what I just wrote (ReplyText) back to First View.
}
}
В моем решении есть папка с именем "Models", но для простоты она пуста.
Я знаю, что есть решения с вспомогательными классами или сервисами - что бы ни делало mvvm. Я также знаю, что выполнение этого для такой простой задачи, как то, что я хочу, является тихим «излишним», и в нем содержится гораздо больше кода для написания, чем это было бы оправдано для этой цели. Но опять же: я хотел бы узнать это и понять, что я делаю.
Заранее большое спасибо!
