Search code examples
c#uwpuwp-xaml

UWP can not x:bind data in ControlTemplate of MediaTransportControls


I am customizing the MediaTransportControls in UserControl.

But in ControlTemplate with TargetType="MediaTransportControls",

I can not x:bind or binding the data in code-behind.

At line TextBlock Text="{x:Bind localTime, Mode=OneWay}" , x:Bind localTime can not work. There is an error "The property 'localTime' was not found in type 'MediaTransportControls"

I think that x:bind only finds properties in MediaTransportControls.

How to x:bind find properties in my UserControl code-behind?

Here is my UserControl xaml

<UserControl.Resources>
    <Style x:Key="CustomMediaTransportControls" TargetType="MediaTransportControls">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="VerticalAlignment" Value="Bottom"/>
        <Setter Property="IsEnabled" Value="True"/>
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="MediaTransportControls">
                    <Grid>
                        <TextBlock Text="{x:Bind localTime, Mode=OneWay}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>


<Grid>
    <MediaPlayerElement x:Name="myMediaPlayerElement"
                        AutoPlay="False"
        <MediaPlayerElement.TransportControls>
            <MediaTransportControls Style="{StaticResource CustomMediaTransportControls}"/>
        </MediaPlayerElement.TransportControls>
    </MediaPlayerElement>
</Grid>

Here is my UserControl code-behind

public sealed partial class MainMedia : UserControl
{
    private string localTime = "My Local Time";

    public MainMedia()
    {
        this.InitializeComponent();
    }
}

Solution

  • It is recommended to use x:bind in UserControl, but currently you need to modify a ControlTemplate in UserControl and bind it to codebehind. In my test, DependencyProperty can only be bound once. What is displayed in MediaTransportControls is only the default value of DependencyProperty, which cannot be changed, This behavior is similar to "mode=oneTime".

    Here is a solution, add another UserControl(UserTextControl) to the ControlTemplate of MediaTransportControls, which can display the current time.

    MyUserControl1.xaml

    <UserControl.Resources>
        <Style x:Key="CustomMediaTransportControls" TargetType="MediaTransportControls">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="VerticalAlignment" Value="Bottom"/>
            <Setter Property="IsEnabled" Value="True"/>
            <Setter Property="IsTabStop" Value="False"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="MediaTransportControls">
                        <StackPanel Background="White">
                            <local:UserTextControl/>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>
    
    
    <Grid>
        <MediaPlayerElement x:Name="myMediaPlayerElement"
                        AutoPlay="True" Source="ms-appx:///Assets/sample-5s.mp4" AreTransportControlsEnabled="True">
            <MediaPlayerElement.TransportControls>
                  <MediaTransportControls Style="{StaticResource CustomMediaTransportControls}"/>
            </MediaPlayerElement.TransportControls>
        </MediaPlayerElement>
    </Grid>
    

    UserTextControl.xaml

    <Grid Background="White">
        <TextBlock Text="{x:Bind localTime,Mode=OneWay}"/>
    </Grid>
    

    UserTextControl.xaml.cs

    public sealed partial class UserTextControl : UserControl
    {
        DispatcherTimer Timer = new DispatcherTimer();
        public UserTextControl()
        {
            this.InitializeComponent();
    
            Timer.Tick += Timer_Tick;
            Timer.Interval = new TimeSpan(0, 0, 1);
            Timer.Start();
        }
    
        private void Timer_Tick(object sender, object e)
        {
    
            GeographicRegion userRegion = new GeographicRegion();
            string regionCode = userRegion.CodeTwoLetter;
    
            DateTimeFormatter timeFormatter = new DateTimeFormatter("year month day hour minute second", new[] { regionCode });
            localTime = timeFormatter.Format(DateTime.Now);
    
        }
    
        public static readonly DependencyProperty localTimeProperty =
      DependencyProperty.Register("localTime", typeof(string), typeof(UserTextControl), new PropertyMetadata("UserTextControl default string"));
      
    
        public string localTime
        {
            get { return (string)GetValue(localTimeProperty); }
            set { SetValue(localTimeProperty, value); }
        }
    }