#c# #wpf #mvvm
#c# #wpf #mvvm
Вопрос:
Я пытался разобраться в mvvm в течение последней недели или больше и все еще испытываю некоторые трудности. Я посмотрел видео Джейсона Долингерса по MVVM и прошел уроки Рида Копси, и все еще задаюсь вопросом, правильно ли я это делаю … я создал очень простое приложение для синхронизации, которое я опубликую ниже. Результат программы соответствует ожиданиям, однако меня больше интересует, действительно ли я правильно использую шаблон. Любые мысли, комментарии и т.д. Были бы оценены.
моя модель
using System;
using System.Threading;
namespace Clock
{
public class ClockModel
{
private const int TIMER_INTERVAL = 50;
private DateTime _time;
public event Action<DateTime> TimeArrived;
public ClockModel()
{
Thread thread = new Thread(new ThreadStart(GenerateTimes));
thread.IsBackground = true;
thread.Priority = ThreadPriority.Normal;
thread.Start();
}
public DateTime DateTime
{
get
{
return _time;
}
set
{
this._time = value;
if (TimeArrived != null)
{
TimeArrived(DateTime);
}
}
}
private void GenerateTimes()
{
while (true)
{
DateTime = DateTime.Now;
Thread.Sleep(TIMER_INTERVAL);
}
}
}
}
мое мнение
<Window x:Class="Clock.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModels="clr-namespace:Clock"
Title="MainWindow" Height="75" Width="375">
<Window.DataContext>
<ViewModels:ClockViewModel />
</Window.DataContext>
<StackPanel Background="Black">
<TextBlock Text="{Binding Path=DateTime}" Foreground="White" Background="Black" FontSize="30" TextAlignment="Center" />
</StackPanel>
</Window>
моя модель представления
using System;
using System.ComponentModel;
namespace Clock
{
public class ClockViewModel : INotifyPropertyChanged
{
private DateTime _time;
private ClockModel clock;
public ClockViewModel()
{
clock = new ClockModel();
clock.TimeArrived = new Action<DateTime>(clock_TimeArrived);
}
private void clock_TimeArrived(DateTime time)
{
DateTime = time;
this.RaisePropertyChanged("DateTime");
}
public DateTime DateTime
{
get
{
return _time;
}
set
{
_time = value;
}
}
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises the property changed event.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
Комментарии:
1. Может быть, лучше подходит для codereview.stackexchange.com , не слишком уверен.
Ответ №1:
То, как вы это делаете, прекрасно. Есть только одна вещь, которую я бы изменил: переместите вызов на RaisePropertyChange
в установщик свойства. Обычно это делается именно так, и это не позволяет вам забыть вызвать уведомление при установке свойства.
Ответ №2:
На мой взгляд, ваша реализация выглядит неплохо с точки зрения разделения задач, хотя вам может быть интересно делегировать свой Model
метод Command
, тогда вы могли бы присоединить его, скажем, к Loaded
событию вашего основного пользовательского интерфейса. Это определенно личное предпочтение, но в качестве хорошей практики я стараюсь поддерживать соотношение 1: 1 между View
: ViewModel
и Model.Method
: Command
Комментарии:
1. хммм, думаю, вы меня тут потеряли, я почитаю о командах и посмотрю, смогу ли я лучше понять, что вы имеете в виду
2. извините за это — итак, идея состоит в том, чтобы иметь как можно более слабо связанные вещи, а именно, было бы предпочтительнее реализовать командование вместо обработки событий, то есть не подписываться на
clock.TimeArrived
событие «напрямую», а через реализациюICommand
вместо этого3. Не могли бы вы случайно привести и пример, сэр. Большинство статей, которые я прочитал сегодня вечером, иллюстрируют привязку команды к кнопке, но я не понимаю, как это заменит мое событие.
4. безусловно — я полагаю, вы могли бы найти
EventToCommand
поведение, доступное в MVVM Light Toolkit ( galasoft.ch/mvvm ) довольно интересно, что это позволяет вам (цитирую сейчас) «привязать любое событие любого элемента пользовательского интерфейса к ICommand, например, в ViewModel, непосредственно в XAML. Это значительно упрощает использование команд без написания кода. С новейшей версией вы даже можете получить EventArgs запущенного события непосредственно в ViewModel для его обработки.»
Ответ №3:
Для некоторых обычных функций использовать MVVM довольно легко, когда вы начинаете касаться окна отображения сообщения. отображение отдельных окон и обмен данными между view и viewmodel. тогда вы обнаружите кое-что сложное..
Комментарии:
1. Да, это, безусловно, так, и мне еще предстоит увидеть хороший пример, который показывает, как сделать такую вещь удобным для обслуживания и простым способом. В итоге я создаю кучу глобальных данных, используемых для обмена данными между представлениями, и я не вижу, насколько это хороший дизайн. MVVM меня немного бесит … : D