Caliburn.Micro / IHandle / EventAggregator中的属性未更新

时间:2018-10-31 03:13:11

标签: events caliburn.micro

这是步骤。

  1. 触发EventAggregator并发送一条消息。
  2. 在IHandle中捕获消息。
  3. 更新TextBlock。(完全不更新TextBlock绑定:(

这是一个简单的逻辑。但不适用于Caliburn.Micro。请检查我的密码。

I make a sample project in 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是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 :(得分:1)

如果您想要一个干净的代码:

不要初始化私有变量_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中调用了final方法:

    /// <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));
            });
        }
    }

答案 1 :(得分:0)

在您的财产current_user内的MyText块中,编写以下代码:

set

set { Debug.WriteLine($ "this.Set(ref _myText, value);"); this.Set(ref _myText, value); NotifyOfPropertyChange(() => MyText); } 方法内,请删除所有Handle,因为无论何时更改values属性,您现在都在调用它。