Похоже, проблема в том, что модель представления зависит от жизненного цикла представления - это автоматически означает, что представление будет уведомлять модель представления о переходах состояний. Цель состоит в том, чтобы найти лучшее представление об этих изменениях.
Первый шаг - изменить структуру взаимодействия: Start()
и Stop()
являются императивными концепциями, которые, я согласен, кажутся тяжелыми. Вместо этого давайте подумаем о том, что мы делаем как конечный автомат. Я предполагаю, что ваши потоки слушают, поэтому наши состояния могут быть Listening
, Idle
и Complete
. Они соответственно будут соответствовать запущенным потокам, приостановленным потокам и потокам, готовым к завершению.
Надежным способом представления состояний является перечисление:
public enum ListenerState
{
Idle,
Listening,
Complete
}
Вы бы объявили свойство этого типа в вашей модели представления:
public class ListenerModel : ViewModel
{
private ListenerState _state;
public ListenerState State
{
get { return _state; }
set
{
_state = value;
RaisePropertyChanged("State");
}
}
}
Затем вы будете прослушивать изменения в состоянии и обновлять поток в соответствии:
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if(e.PropertyName == "State")
{
// Manipulate thread for current state
}
}
Теперь представление просто должно уведомить модель представления о событиях жизненного цикла (что-то, что модель представления не могла знать иначе, кроме как из представления):
private void OnLoaded(object sender, RoutedEventArgs e)
{
((ListenerModel) this.DataContext).State = ListenerState.Listening;
}
Если вы хотите полностью отделить представление от модели представления, вы можете создать свойство зависимости в вашем элементе управления для состояния:
public static readonly DependencyProperty ListenerStateProperty =
DependencyProperty.Register("ListenerState", typeof(ListenerState), typeof(YourControl), null);
public ListenerState ListenerState
{
get { return (ListenerState) GetValue(ListenerStateProperty); }
set { SetValue(ListenerStateProperty, value); }
}
Затем установите это свойство в обработчике Loaded
вместо ссылки на модель представления:
private void OnLoaded(object sender, RoutedEventArgs e)
{
this.ListenerState = ListenerState.Listening;
}
Наконец, вы должны привязать свойство к свойству модели представления в разметке:
<local:YourControl ListenerState="{Binding State, Mode=TwoWay}" />