Какой метод в WPF срабатывает при смене UserControl в ContentControl?

421
29 апреля 2017, 20:08

В приложении по клику на разные кнопки меню в ContentControl подгружаются разные вьюшки. В каждой вьюьшке идет запрос к базе данных, каждую секунду в цикле, для обновления данных, получается что при переходе на другую вьюху, в предыдущей продолжает выполнятся метод, какое событие срабатывает при этом?

Это метод который каждую секунду срабатывает во ViewModel

CancellationTokenSource ct = null;
async void DBAsync()
{
    while (true)
    {
        try
        {
            if (ct == null)
                ct = new CancellationTokenSource();
        }
        catch (InvalidOperationException)
        {
        }
        if (ct == null)
        {
            break;
        }
        try
        {
            await Task.Delay(TimeSpan.FromSeconds(3), ct.Token);
            await Task.Run(() => getDataDB());
        }
        catch (OperationCanceledException)
        {
        }
    }
}
Answer 1

В ContentControl при изменении свойства Content срабатывает метод OnContentChanged, но к сожалению не существует стандартного события ContentChanged, на которое можно было бы подписаться и узнавать таким образом об изменениях View внутри ContentControl.

Но никто не мешает вам определить это событие самостоятельно:

public class CustomContentControl : ContentControl
{
    public delegate void ContentChangeEventHandler(object sender, ContentChangedEventArgs e);
    public static readonly RoutedEvent ContentChangedEvent
        = EventManager.RegisterRoutedEvent(
            nameof(ContentChanged),
            RoutingStrategy.Bubble,
            typeof(ContentChangeEventHandler),
            typeof(CustomContentControl));
    public event ContentChangeEventHandler ContentChanged
    {
        add => AddHandler(ContentChangedEvent, value);
        remove => RemoveHandler(ContentChangedEvent, value);
    }
    protected override void OnContentChanged(object oldContent, object newContent)
    {
        var ea = new ContentChangedEventArgs(ContentChangedEvent, this) {NewContent = newContent};
        RaiseEvent(ea);
        base.OnContentChanged(oldContent, newContent);
    }
}
public class ContentChangedEventArgs : RoutedEventArgs
{
    public object NewContent { get; set; }
    public ContentChangedEventArgs() : base() { }
    public ContentChangedEventArgs(RoutedEvent routedEvent) : base(routedEvent) { }
    public ContentChangedEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source) { }
}
Answer 2

Раз ваш метод выполняется в VM, ему не стоит знать о том, что есть во View. Ваш код должен по идее быть организован так:

  1. По клику на кнопки вызывается через Binding команда в «большой» VM.
  2. У вас в VM есть свойство ActivePart, отвечающее за текущую активную «маленькую» VM, и список этих самых «маленьких» VM. Вызванная команда вызывает у активной маленькой VM метод Deactivate, присваивает ActivePart новую маленькой VM из списка, и вызывает у неё метод Activate.
    • Для этого все маленькой VM должны имплементировать общий интерфейс, или быть порождёнными от общего базового класса.
  3. В методе Activate VM запускает метод наподобие DBAsync, а в методе Deactivate останавливает его. Для этого проще всего завести в маленькой VM поле bool flag, цикл while (true) поменять на while (flag), и при необходимости оборвать цикл просто устанавливать flag = false;.
READ ALSO
Как сделать sprite во весь экран?

Как сделать sprite во весь экран?

Как сделать sprite во весь экран (Независимую размерность, унив?

303
Синхронизация процессов - RR строгое чередование для 2 процессов

Синхронизация процессов - RR строгое чередование для 2 процессов

Помогите написать на любом языке программу, которая

503
Начать игру по нажатию ENTER!

Начать игру по нажатию ENTER!

Это код игры в WindowsFormПри открытии игра сразу начинает работать но нужно что бы было по нажатию ENTER, как это сделать это я не понял

294
Как проверять в редиректе REQUEST массив?

Как проверять в редиректе REQUEST массив?

Есть задача сделать редирект с https://wwwsite

230