0

I am just getting started with Caliburn Micro and trying to wrap my head around IResult. To do so, I have written some dummy code. The code is meant to display "Loading..." in a text box until some lengthy operation (Task.Delay) completes, at which point the text should disappear. Here is my code:

ViewModel:

[Export(typeof(IShell))]
public class ShellViewModel : IShell
{
    public string MyMessage { get; set; }

    public IEnumerable<IResult> DoSomething()
    {
        yield return Loader.Show("Loading...");
        yield return Task.Delay(1000).AsResult();
        yield return Loader.Hide(); 
    }
}

View:

<Window x:Class="CaliburnMicroTest.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CaliburnMicroTest"
        xmlns:cal="http://www.caliburnproject.org"
        mc:Ignorable="d"
        Title="ShellView" Height="300" Width="300">
    <StackPanel>
        <Button Content="Do Something"
                x:Name="DoSomething" />
        <TextBox Text="{Binding Path=MyMessage, Mode=TwoWay}"/>
    </StackPanel>
</Window>

Loader class:

public class Loader : IResult
{
    readonly string message;
    readonly bool hide;

    public Loader(string message)
    {
        this.message = message;
    }

    public Loader(bool hide)
    {
        this.hide = hide;
    }

    public event EventHandler<ResultCompletionEventArgs> Completed;

    public void Execute(CoroutineExecutionContext context)
    {
        var target = context.Target as ShellViewModel;

        target.MyMessage = hide ? string.Empty : message;

        Completed(this, new ResultCompletionEventArgs());
    }

    public static IResult Show(string message = null)
    {
        return new Loader(message);
    }

    public static IResult Hide()
    {
        return new Loader(true);
    }
}

When I click the button, I expect the textbox to be populated with "Loading..." for one second and then become empty again, but nothing ever shows up in the textbox. Additionally, when I debug, the MyMessage property on my ViewModel has a value of "Loading...". Why would the text not show up on my view?

1 Answers1

1

Your view model class should inherit from PropertyChangedBase and raise change notifications:

[Export(typeof(IShell))]
public class ShellViewModel : IShell, PropertyChangedBase
{
    string _myMessage;
    public string MyMessage
    {
        get { return _myMessage; }
        set
        {
            _myMessage = value;
            NotifyOfPropertyChange(() => MyMessage);
        }
    }

    public IEnumerable<IResult> DoSomething()
    {
        yield return Loader.Show("Loading...");
        yield return Task.Delay(1000).AsResult();
        yield return Loader.Hide();
    }
}
mm8
  • 163,881
  • 10
  • 57
  • 88