Search code examples
uwpmedia-playeruwp-xaml

How to detect the event when media transport controls show and hide


I'm using MediaPlayerElement. Currently the media transport controls can show and hide itself. But there is no event to indicate when to show and hide.

Is there any workaround? Thx.

<MediaPlayerElement x:Name="viuMediaPlayer" AreTransportControlsEnabled="True">
        <MediaPlayerElement.TransportControls>
            <MediaTransportControls
                x:Name="MediaTransportControls_Custom"/>
        </MediaPlayerElement.TransportControls>
    </MediaPlayerElement>

en


Solution

  • Currently, UWP does not provide api to detect transport controls show and hide. But you could check MediaTransportControls style. The hide and show animation matched VisualState are ControlPanelFadeIn and ControlPanelFadeOut.

    <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>
    

    So you could detect TranslateVertical Y property changed to recognise MediaTransportControls hide or show state.

     var PanelGrid = MyFindListViewChildByName(MyControl, "ControlPanelGrid") as Grid;
     var render = PanelGrid.RenderTransform;
     var watcher = new DependencyPropertyWatcher<string>(render, "Y");
     watcher.PropertyChanged += Watcher_PropertyChanged;
    
    private void Watcher_PropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
    
        if ((double)e.NewValue == 50)
        {
            System.Diagnostics.Trace.WriteLine("hide");
        }
        else if ((double)e.NewValue == 0.5)
        {
            System.Diagnostics.Trace.WriteLine("show");
        }
    
    }
    

    But the is a problem in above, if the thread that host above event exist, the Watcher_PropertyChanged will be unavailable.

    Refer tool class

    public static DependencyObject MyFindListViewChildByName(DependencyObject parant, string ControlName)
    {
        int count = VisualTreeHelper.GetChildrenCount(parant);
    
        for (int i = 0; i < count; i++)
        {
            var MyChild = VisualTreeHelper.GetChild(parant, i);
            if (MyChild is FrameworkElement && ((FrameworkElement)MyChild).Name == ControlName)
                return MyChild;
    
            var FindResult = MyFindListViewChildByName(MyChild, ControlName);
            if (FindResult != null)
                return FindResult;
        }
    
        return null;
    }
    
    
    public class DependencyPropertyWatcher<T> : DependencyObject, IDisposable
    {
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register(
                "Value",
                typeof(object),
                typeof(DependencyPropertyWatcher<T>),
                new PropertyMetadata(null, OnPropertyChanged));
    
        public event DependencyPropertyChangedEventHandler PropertyChanged;
    
        public DependencyPropertyWatcher(DependencyObject target, string propertyPath)
        {
            this.Target = target;
            BindingOperations.SetBinding(
                this,
                ValueProperty,
                new Binding() { Source = target, Path = new PropertyPath(propertyPath), Mode = BindingMode.OneWay });
        }
    
        public DependencyObject Target { get; private set; }
    
        public T Value
        {
            get { return (T)this.GetValue(ValueProperty); }
        }
    
        public static void OnPropertyChanged(object sender, DependencyPropertyChangedEventArgs args)
        {
            DependencyPropertyWatcher<T> source = (DependencyPropertyWatcher<T>)sender;
    
            if (source.PropertyChanged != null)
            {
                source.PropertyChanged(source.Target, args);
            }
        }
    
        public void Dispose()
        {
            this.ClearValue(ValueProperty);
        }
    }
    

    Certainly, the better is that post your requirement in UserVoice ask our team for this new feature.