0

Here is my simple test project to try Caliburn.Micro+UWP.

enter image description here

There is 2 button.

  • Save : it make action on HelloViewModel. ( It worked : )
  • Bubble Save : I expect it make action on ParentViewModel but Not work... :(

Could you give me your idea ? Why ???

Here is project file on Github.

First is HelloViewMode code. This work fine.

public void Save()
    {
        Debug.WriteLine("Click Save");
    }

2nd is ParentViewMode code. This not work... I wonder...

public void BubbleSave()
    {
        Debug.WriteLine("Click BubbleSave");
    }

and HelloView XAML code is here.

        <Button x:Name="Save" Content="SaveButton" Margin="30"/>
        <Button x:Name="BubbleSave" Content="Bubble SaveButton" Margin="30"/>

I expected to be called BubbleSave.... but Not be called.

Thank you for helping me.

Kazuhiko Nakayama
  • 801
  • 1
  • 8
  • 24
  • Paste here only relevant code and describe what doesnt work. – FCin Aug 17 '17 at 08:12
  • I added some main code in Question. Thank you ! – Kazuhiko Nakayama Aug 17 '17 at 08:42
  • Your `BubbleSave` is in a different class so how do you expect it to work? – FCin Aug 17 '17 at 09:01
  • The DataContext of your HelloView is HelloViewModel. Caliburn won't be able to resolve the Method for BubbleSave. Since you are using conventions to bind the methods you won't see any BindingErrors in the output. I prefer to bind to the Command property of the button, with an ICommand which means you should be able to see any binding errors in the output window. – jsmyth886 Aug 17 '17 at 09:23

1 Answers1

2

Basically you want to notify parent that BubbleSave was pressed. Your child class doesn't know anything about your parent, so it cannot call it. Solution here is to either create an interface or an event. I can see that you use dependency injection.

Your HelloViewModel needs to know a little bit about it's parent. It needs to know that BubbleSave exists, so you can create interface:

public interface IBubbleSave {
    void BubbleSave();
}

and assign it to ParentViewModel:

public class ParentViewModel: Conductor<object>, IBubbleSave

The child should require this interface to be able to call the method.

public class HelloViewModel : Screen
{
    private readonly IBubbleSave _bubbleSave;
    public HelloViewModel(IBubbleSave bubbleSave) {
         _bubbleSave = bubbleSave;
    }
    public void Save()
    {
        Debug.WriteLine("Click Save");
    }
    public void BubbleSave()
    {
        _bubbleSave.BubbleSave();
    }
}

You also have to register dependency for IBubbleSave in your App.xaml.cs


Second way of doing this is to use events.

Your HelloViewModel can expose event that the parent subscribes to:

public class HelloViewModel : Screen
{
    public event EventHandler BubbleSavePressedEvent;
    public void Save()
    {
        Debug.WriteLine("Click Save");
    }

    public void BubbleSave()
    {
        BubbleSavePressedEvent?.Invoke();
    }
}

public class ParentViewModel : Conductor<object>
{
    HelloViewModel _helloViewModel;

    public ParentViewModel(HelloViewModel helloViewModel)
    {
        _helloViewModel = helloViewModel;
        _helloViewModel.BubbleSavePressedEvent += BubbleSave;

        ActivateItem(_helloViewModel);
    }

    public void BubbleSave()
    {
        Debug.WriteLine("Click BubbleSave");
    }
}
FCin
  • 3,804
  • 4
  • 20
  • 49