Search code examples
c#eventscaliburn.micro

CaliburnMicro IsVisibleChanged does not fire


The event IsVisibleChanged couldn't be routed to the ViewModel. What could be the cause?

If I'm testing the event as normal WPF event (no Caliburn Message.Atach) with CodeBehind, the Event is fired as expected. If I'm testing the Caliburn Message.Atach with other events of the UserControl like LayoutUpdated, they work like expected with the ViewModel. But I'm not able to get IsVisibleChanged fired to my ViewModel.

View

<UserControl x:Class="MySetupDeviceConfig.Views.SetupDeviceConfigView" 
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:cal="http://www.caliburnproject.org"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" Visibility="{Binding Visibility}"
         d:DesignHeight="450" d:DesignWidth="800" 
         cal:Message.Attach="[Event IsVisibleChanged] = [Action UcIsVisibleChanged];">
    <Grid>
    ...

ViewModel

public class SetupDeviceConfigViewModel : Screen
{
    private Visibility _Visibility;
    private ILogger Log { get; set; }
    public Visibility Visibility { get => _Visibility; set { _Visibility = value; NotifyOfPropertyChange(); } }

    // ...

    public void UcIsVisibleChanged()
    {
        Log.LogInformation("IsVisibleChanged");
    }

Tested with Caliburn.Micro v4.0.62-alpha and CaliburnMicro v3.2.0

Changing e.g. to the Loaded event in the view with same action/function mapping -> it works. So there is no type mismatch...

    cal:Message.Attach="[Event Loaded] = [Action UcIsVisibleChanged];">

Solution

  • The reason for this not working is that IsVisibleChanged is a CLR event and not a routed event. As stated in the documentation.

    Caliburn.Micro's Message system works on routed event not CLR events. Since Caliburn.Micro uses EventTrigger internally.

    Why not just make a binding to IsVisible?