Search code examples
c#xamluwpvisualstatemanagervisualstates

uwp get notification for visual state changed in Custom Media Controls


in my uwp app I have Custom Media Transport Controls and I want to get notified whenever my controls appear and disappear from screen so I can match the cursor appear and disappear with it as well.

this is what I have tried so far :

From generic.xaml in my style of controls I found following VisualStateGroup which controls the fadein and fadeout of controls.

<VisualStateGroup x:Name="ControlPanelVisibilityStates">
    <VisualState x:Name="ControlPanelFadeIn">
        <Storyboard>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ControlPanel_ControlPanelVisibilityStates_Border">
                <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1" />
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimation Storyboard.TargetProperty="Y" Storyboard.TargetName="TranslateVertical" From="50" To="0.5" Duration="0:0:0.3" />
        </Storyboard>
    </VisualState>
    <VisualState x:Name="ControlPanelFadeOut">
        <Storyboard>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ControlPanel_ControlPanelVisibilityStates_Border">
                <EasingDoubleKeyFrame KeyTime="0" Value="1" />
                <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0" />
            </DoubleAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="ControlPanel_ControlPanelVisibilityStates_Border">
                <DiscreteObjectKeyFrame KeyTime="0" Value="False" />
            </ObjectAnimationUsingKeyFrames>
            <DoubleAnimation Storyboard.TargetProperty="Y" Storyboard.TargetName="TranslateVertical" From="0.5" To="50" Duration="0:0:0.7" />
        </Storyboard>
    </VisualState>
</VisualStateGroup>

So I thought I should get this group in my OnApplyTemplate method and then assign the state changed event to it.

protected override void OnApplyTemplate()
{
    //other irrelivent code
    ControlsFade = (VisualStateGroup)GetTemplateChild("ControlPanelVisibilityStates");
        ControlsFade.CurrentStateChanged += 
    ControlsFade_CurrentStateChanged;
    base.OnApplyTemplate();
}

public class ControlFadeChangedEventArgs
{
    public bool Appeared { get; set; }
}
public event EventHandler<ControlFadeChangedEventArgs> ControlFadeChanged;

private void ControlsFade_CurrentStateChanged(object sender, VisualStateChangedEventArgs e)
{
    bool fadein = false;
    if (e.NewState.Name == "ControlPanelFadeIn")
            fadein = true;

    ControlFadeChanged?.Invoke(this, new ControlFadeChangedEventArgs { Appeared = fadein });
}

I wired it all up and further logic is being done on the page, which is irrelevant in this case. I debugged with a break point and found out that ControlsFade_CurrentStateChanged is never firing.


Solution

  • Within my custom controls I was unsubscribing to all the events related to my custom media controls in the UnLoaded event of the media controls( including the ControlsFade_CurrentStateChanged) and as it turns out whenever controls go fullscreen, the Unloaded event is triggered so it removed the subscription to this event and hence it was not firing after that. so I commented out the unloaded event and now it is working as expected.

    Unsubscription of events is important to prevent memory leaks, please let me know in the comments how I can unsubscribe without causing this issue.