WPF Mediaelement event recorded in a media file is not triggered from the code behind but with a click handler

First post so be careful and sorry for the long post but wanted to provide as much detail as possible.

I have a MediaElement inside a usercontrol with the LoadedBehaviour property set manually, see below. When I click the Open button, the handler code includes playing the media files so that I can prepare the execution duration in the MediaOpened event handler, which it successfully executes. The MediaOpened handler stops playback when I only need the length of the media.

I also want to load the playlist at the beginning of the program and populate the datagrid with information, with one item being the length of the media.

XAML

    <MediaElement Grid.Row="5" Name="MediaEL" Grid.ColumnSpan="6" MediaOpened="MediaEL_MediaOpened"  LoadedBehavior="Manual" Height="169" />

    <DataGrid Grid.Row="1" Grid.ColumnSpan="6"  Name="dgPlayList" AutoGenerateColumns="False" Height="300" >
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Position}" Header="#" Width="30"/>
            <DataGridTextColumn Binding="{Binding Title}" Header="Title" Width="182"/>
            <DataGridTextColumn Binding="{Binding Time}" Header="Time" Width="50"/>
            <DataGridCheckBoxColumn Binding="{Binding Dnp}" Header="Dnp" Width="35"/>
            <DataGridTextColumn Binding="{Binding Location}" Visibility="Hidden" />
        </DataGrid.Columns>
    </DataGrid>

      

FROM#

    private void btnOpen_Click(object sender, RoutedEventArgs e)  
    {  
        System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();  

        if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)  
        {  
            MediaEL.Source = new Uri(ofd.FileName);
            btnPlay.IsEnabled = true;
            MediaEL.Visibility = Visibility.Hidden;
            SettingTime = true;
            MediaEL.Play();
        }
    }

    private void MediaEL_MediaOpened(object sender, RoutedEventArgs e)
    {
        if (MediaEL.NaturalDuration.HasTimeSpan)
        {
            TimeSpan ts = MediaEL.NaturalDuration.TimeSpan;
            Length.Content = FormatLength(ts.TotalSeconds);  // make it look like 00:00:00
            seekBar.Maximum = ts.TotalSeconds;
            seekBar.SmallChange = 1;
            seekBar.LargeChange = Math.Min(10, ts.Seconds / 10);
        }
        if (!SettingTime)
            timer.Start();
        else
        {
            SettingTime = false;
            MediaEL.Stop();
            MediaEL.Visibility = Visibility.Visible;
            MediaEL.Close();
        }
    }

      

dgPlayList.ItemsSource = LoadPlayListData ();

called in window loading mode.
I commented out the method below the foreach statement until I got it working.

Now the PROBLEM is when trying to get the length of the media to populate the data time column, the MediaOpened event is NOT fired and I don't understand why not, and have exhausted my search for this.
Any thoughts would be greatly appreciated!
Thanks Jim

FROM#

    private ObservableCollection<PlayListEntry> LoadPlayListData()
    {
        var playListEntries = new ObservableCollection<PlayListEntry>();
        var position = 1;
        var bPlay = false;

        var doc = new XmlDocument();
        doc.Load(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase) + @"/mpcplaylist.xml");

        var root = doc.DocumentElement;
        var nodes = root.SelectNodes("/playlist/media");

        XmlNode node = nodes[0];

        if (node.InnerXml.Contains("title"))
        {
            var xmlElement = node["title"];
            if (xmlElement != null)
                Title = xmlElement.InnerText;
        }

        if (node.InnerXml.Contains("artist"))
        {
            var xmlElement = node["artist"];
            if (xmlElement != null)
                Artist = xmlElement.InnerText;
        }

        if (node.InnerXml.Contains("location"))
        {
            var xmlElement = node["location"];
            if (xmlElement != null)
                Location = xmlElement.InnerText;
        }

        if (node.InnerXml.Contains("include"))
        {
            var xmlElement = node["include"];
            if (xmlElement != null)
                Include = xmlElement.InnerText;
        }

        if (Include == "No")
            bPlay = true;
        else
            bPlay = false;

        //foreach (XmlNode node in nodes)
        //{
        //    if (node.InnerXml.Contains("title"))
        //    {
        //        var xmlElement = node["title"];
        //        if (xmlElement != null)
        //            Title = xmlElement.InnerText;
        //    }

        //    if (node.InnerXml.Contains("artist"))
        //    {
        //        var xmlElement = node["artist"];
        //        if (xmlElement != null)
        //            Artist = xmlElement.InnerText;
        //    }

        //    if (node.InnerXml.Contains("location"))
        //    {
        //        var xmlElement = node["location"];
        //        if (xmlElement != null)
        //            Location = xmlElement.InnerText;
        //    }

        //    if (node.InnerXml.Contains("include"))
        //    {
        //        var xmlElement = node["include"];
        //        if (xmlElement != null)
        //            Include = xmlElement.InnerText;
        //    }

        //    if (Include == "No")
        //        bPlay = true;
        //    else
        //        bPlay = false;


            MediaEL.Source = new Uri(Location);

            SettingTime = true;

            MediaEL.Play();

            Medialength = Length.Content.ToString();

            playListEntries.Add(new PlayListEntry()
            {
                Dnp = bPlay,
                Position = position++,
                Time = Medialength,
                Title = Title,
                Location = Location
            });


        //}

        return playListEntries;
    }

      

+3


source to share


2 answers


The solution was ...

I take the first entry from the xml playlist and set the source property, then call the play method to get the duration. Now, in the Media Opened event, I will then grab the next entry and do the same until I have a duration for all the media in the list.

This was the key when the event opened by the media got the next entry after the first one was processed.



This says that I have another threading and control issue, but I will create a new entry for this.

Thanks Jim

+2


source


Ok, so I haven't been able to find a complete solution for my version of your problem, but I have identified what is causing my problem with the object MediaPlayer

. My app (and internal media player) worked fine, but it stopped working after the permissions on the folder containing the audio were changed.

The folder was changed to allow read-only access, so MediaPlayer

should still have access to the files. It seemed, however, as if a higher level of permission was required before he could open any file. I tested this with a method WindowsIdentity.Impersonate

, granting full method call permissions MediaPlayer.Open

, but there was no change.

Finally, I tried to pass the path for the audio file on the local filesystem to the method MediaPlayer.Open

and, hey, presto, it all worked again as before! Perhaps you should try doing this in the last step to see if your issue is caused by security permissions.



UPDATE →

Yes, it turned out to be a permission error. The IT department messed up my permissions, so why MediaPlayer

(or the app that inherited my permissions) couldn't open the audio file. After I gave the correct rights MediaPlayer

it started working fine again.

I hope this helps.

0


source







All Articles