Caliburn.Micro / Свойство не обновляется в IHandle / EventAggregator - PullRequest
0 голосов
/ 31 октября 2018

Вот шаг.

  1. Запустите EventAggregator и отправьте сообщение.
  2. Перехватить сообщение в IHandle.
  3. Обновление TextBlock. (Не обновлять привязку TextBlock вообще: (

Это простая логика. но не работает на Caliburn.Micro. Пожалуйста, проверьте мои коды.

Я делаю пример проекта в GitHub.

Вы можете проверить это, просто нажав кнопку.

enter image description here

Вот ViewModel

    public void PublishOnBackgroundThread(int flag) {

        Debug.WriteLine($"PublishOnBackgroundThread/{flag}");
        ix++;
        if( flag == 0)
        {
            _eventAggregator.PublishOnBackgroundThread(new HelloMessage(ix.ToString(), false));
        }
        else if( flag == 1)
        {
            _eventAggregator.PublishOnBackgroundThread(new HelloMessage(ix.ToString(), true));
        }
    }

    public void PublishOnCurrentThread(int flag)
    {
        Debug.WriteLine($"PublishOnCurrentThread/{flag}");
        ix++;
        if (flag == 0)
        {
            _eventAggregator.PublishOnCurrentThread(new HelloMessage(ix.ToString(), false));
        }
        else if (flag == 1)
        {
            _eventAggregator.PublishOnCurrentThread(new HelloMessage(ix.ToString(), true));
        }
    }
    public void PublishOnUIThread(int flag)
    {
        Debug.WriteLine($"PublishOnUIThread/{flag}");
        ix++;
        if (flag == 0)
        {
            _eventAggregator.PublishOnUIThread(new HelloMessage(ix.ToString(), false));
        }
        else if (flag == 1)
        {
            _eventAggregator.PublishOnUIThread(new HelloMessage(ix.ToString(), true));
        }
    }
    public void PublishOnUIThreadAsync(int flag)
    {
        Debug.WriteLine($"PublishOnUIThreadAsync/{flag}");
        ix++;
        if (flag == 0)
        {
            _eventAggregator.PublishOnUIThreadAsync(new HelloMessage(ix.ToString(), false));
        }
        else if (flag == 1)
        {
            _eventAggregator.PublishOnUIThreadAsync(new HelloMessage(ix.ToString(), true));
        }
    }

    public void Handle(HelloMessage message)
    {

        Debug.WriteLine($"Handle(HelloMessage message)/{message.UiAsync}/{message.msg}");
        if (message.UiAsync)
        {
            Execute.OnUIThreadAsync(() =>
            {
                _myText = message.msg;
                MyText = _myText;

            });
            /*Execute.OnUIThread(() =>
            {
                _myText = message.msg;
                MyText = _myText;

            });*/
        }
        else
        {
            _myText = message.msg;
            MyText = _myText;
        }
    }

    private int ix = 0;
    private String _myText = "Update Number at Here !";
    public String MyText
    {
        get { return _myText; }
        set
        {
            Debug.WriteLine($"this.Set(ref _myText, value);");
            this.Set(ref _myText, value);
        }
    }

Nere is xaml.

        <StackPanel.Resources>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Margin" Value="5"/>
            </Style>
        </StackPanel.Resources>

        <TextBlock Text="{Binding MyText, Mode=TwoWay}" Margin="50" />
        <Button Content="PublishOnBackgroundThread" cal:Message.Attach="[Event Click]=[Action PublishOnBackgroundThread(0)]"/>
        <Button Content="PublishOnCurrentThread" cal:Message.Attach="[Event Click]=[Action PublishOnCurrentThread(0)]"/>
        <Button Content="PublishOnUIThread" cal:Message.Attach="[Event Click]=[Action PublishOnUIThread(0)]"/>
        <Button Content="PublishOnUIThreadAsync" cal:Message.Attach="[Event Click]=[Action PublishOnUIThreadAsync(0)]"/>


        <Button Content="PublishOnBackgroundThread + Execute.OnUIThreadAsync" cal:Message.Attach="[Event Click]=[Action PublishOnBackgroundThread(1)]"/>
        <Button Content="PublishOnCurrentThread + Execute.OnUIThreadAsync" cal:Message.Attach="[Event Click]=[Action PublishOnCurrentThread(1)]"/>
        <Button Content="PublishOnUIThread + Execute.OnUIThreadAsync" cal:Message.Attach="[Event Click]=[Action PublishOnUIThread(1)]"/>
        <Button Content="PublishOnUIThreadAsync + Execute.OnUIThreadAsync" cal:Message.Attach="[Event Click]=[Action PublishOnUIThreadAsync(1)]"/>

StackOverFlow Веб-страница не любит длинный код. затем я печатаю ........

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Если вы хотите чистый код:

не инициализировать приватную переменную _myText, но MyText в конструкторе

    private readonly IEventAggregator _eventAggregator;
    public BaseViewModel()
    {
        MyText = "Update Number at Here !";
        _eventAggregator = IoC.Get<IEventAggregator>();
    }

и лучше, если вы используете инъекцию зависимостей:

    private readonly IEventAggregator _eventAggregator;
    public BaseViewModel(IEventAggregator _eventAggregator)
    {
        MyText = "Update Number at Here !";
        this._eventAggregator = _eventAggregator;
    }

затем объявите свойство:

private String _myText;
public String MyText
{
    get { return _myText; }
    set
    {
        Debug.WriteLine($"this.Set(ref _myText, value);");
        this.Set(ref _myText, value); // or
        //_myText = value;
        //NotifyOfPropertyChange(() => MyText);
    }
}

и, наконец, дескриптор:

    public void Handle(HelloMessage message)
    {
        Debug.WriteLine($"Handle(HelloMessage message)/{message.UiAsync}/{message.msg}");
        if (message.UiAsync)
        {
            Execute.OnUIThreadAsync(() =>
            {
                MyText = message.msg;

            });
            /*Execute.OnUIThread(() =>
            {
                _myText = message.msg;
                MyText = _myText;

            });*/
        }
        else
        {
            MyText = message.msg;
        }
    }

Не обновлять закрытую переменную _myText, а только открытую переменную MyText

каждый раз, когда вы обновляете переменную MyText, NotifyOfPropertyChange отправляет обновление представлению.

используя this.Set или две строки в комментариях одинаковы .. обе они вызывают последний метод в caliburn:

    /// <summary>
    /// Notifies subscribers of the property change.
    /// </summary>
    /// <param name="propertyName">Name of the property.</param>
    // Token: 0x060000BF RID: 191 RVA: 0x0000342C File Offset: 0x0000162C
    public virtual void NotifyOfPropertyChange([CallerMemberName] string propertyName = null)
    {
        if (this.IsNotifying && this.PropertyChanged != null)
        {
            this.OnUIThread(delegate
            {
                this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
            });
        }
    }
0 голосов
/ 31 октября 2018

Внутри вашей собственности MyText, в set блоке напишите это:

set {
    Debug.WriteLine($ "this.Set(ref _myText, value);");
    this.Set(ref _myText, value);
    NotifyOfPropertyChange(() => MyText);
}

А внутри Handle метода удалите все NotifyOfPropertyChange(() => MyText);, так как вы теперь вызываете его, когда вы изменяете свойство values.

...