Reputation: 801
Here is step.
It is a simple logic. but not work on Caliburn.Micro. Please check my codes.
I make a sample project in GitHub.
You can test it with just click button.
Here is 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 Web page do not like long code. then, I am typing........
Upvotes: 0
Views: 677
Reputation: 17017
If you want a clean code:
dont initialize the private variable _myText, but MyText in the constructor
private readonly IEventAggregator _eventAggregator;
public BaseViewModel()
{
MyText = "Update Number at Here !";
_eventAggregator = IoC.Get<IEventAggregator>();
}
and better if you use the Dependency Injection:
private readonly IEventAggregator _eventAggregator;
public BaseViewModel(IEventAggregator _eventAggregator)
{
MyText = "Update Number at Here !";
this._eventAggregator = _eventAggregator;
}
then declare the property:
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);
}
}
and finally Handle:
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;
}
}
Dont update the private variable _myText, but only the public variable MyText
each time you update the MyText variable, the NotifyOfPropertyChange sends the update to the view.
using this.Set or the two lines in comments is the same.. both they call the final method in 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));
});
}
}
Upvotes: 2
Reputation: 1211
Inside your property MyText
, in set
block write this:
set {
Debug.WriteLine($ "this.Set(ref _myText, value);");
this.Set(ref _myText, value);
NotifyOfPropertyChange(() => MyText);
}
And inside Handle
method remove all NotifyOfPropertyChange(() => MyText);
since your are now calling it when ever you change the values property.
Upvotes: 0