locked
Binding a MediaElement in a Listview ? RRS feed

  • Question

  • Hi  ,

    I'm building a Metro UI C# app.

    I'm trying to bind a media element in a list view but I cannot get it to work.

    My XAML looks like the below

    <ListView.ItemTemplate >
                                <DataTemplate >
                                    <Grid   Margin="6" x:Name="DatagridPhotosTemplate" >
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="80"/>
                                        </Grid.RowDefinitions>

                                      
                                        <Canvas x:Name='playbackCanvas2' Width="470"  Height="470" Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                                            <MediaElement  x:Name='playbackElement2' Source="{Binding VideoLogo}" Visibility= "Visible" Width="470"  Height="470" />
                                        </Canvas>

                                        <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0" Width="170" >
                                            <TextBlock Text="{Binding Caption}" Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/>
                                            <TextBlock Text="{Binding FileName}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
                                            <TextBlock Text="{Binding Comments}" Style="{StaticResource BodyTextStyle}" MaxHeight="90"/>
                                        </StackPanel>


                                    </Grid>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>

    And in the code behind

      MediaElement MyElement = new MediaElement();
                                var stream1 = await MyFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
                                  //the stream1 has data. It is not zero                   
                                 MyElement.SetSource(stream1, ".mp4");

    .

    .

    .

    some code and then I bind the listview.

     
                    this.itemPhotosListView.ItemsSource = null;
                    this.itemPhotosListView.ItemsSource = MyCurrentPhotos;

    I think that the SetSource is failing. The binding works for the rest of my properties so I'm OK with that.

    But when I try run the setSource command after I check in debugging the source property I found it null. .

    Any ideas ?

    Appreciate any help you could give me.


    • Edited by zakkar Saturday, August 10, 2013 4:37 AM
    Friday, August 9, 2013 11:16 AM

Answers

  • I've got a crazy implementation where I got this to work.  It was more difficult than I realized.  It's not fully formed, please test this out.

    <StackPanel>
      <Button Content="Choose one or more .mp4 videos" Click="Button_Click"/>
      <ListView x:Name="MyListView">
        <ListView.ItemTemplate>
          <DataTemplate>
            <StackPanel>
              <MediaElement Width="200" Height="150" AutoPlay="True" Loaded="MediaElement_Loaded"/>
              <TextBlock Text="{Binding path}" Foreground="White"/>
            </StackPanel>
          </DataTemplate>                
        </ListView.ItemTemplate>
      </ListView>
    </StackPanel>

    public sealed partial class MainPage : Page
    {
      public MainPage()
      {
        this.InitializeComponent();
      }
    
      IReadOnlyList<StorageFile> Videos;
      private async void Button_Click(object sender, RoutedEventArgs e)
      {
        var MyFilePicker = new FileOpenPicker();
        MyFilePicker.FileTypeFilter.Add(".mp4");
        Videos = await MyFilePicker.PickMultipleFilesAsync();
        MediaElementCounter = 0;
        MyListView.ItemsSource = Videos;
      }
    
      int MediaElementCounter;
      private async void MediaElement_Loaded(object sender, RoutedEventArgs e)
      {
        MediaElement CurrentMedia = sender as MediaElement;
        var MediaStream = await Videos  [MediaElementCounter].OpenAsync(Windows.Storage.FileAccessMode.Read);
        CurrentMedia.SetSource(MediaStream, ".mp4");
        MediaElementCounter++;
      }
    }
    
    class MyMediaClass
    {
      public string MyFile { get; set; }
      public MediaElement MyMedia { get; set; }
    }


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    • Marked as answer by zakkar Thursday, August 15, 2013 6:04 AM
    Tuesday, August 13, 2013 4:12 PM
    Moderator

All replies

  • The code is confusing.  The MediaElement in the ListView doesn't have any connection to the Mediaelement called "MyElement".  Where is the information that you are binding to the mediaelement in the listview?


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Friday, August 9, 2013 12:33 PM
    Moderator
  • Hi Matt , 

    This is the class I'm using with some properties

        

     [DataContract]
            public class GalleryList
            {
                private Int32 m_auto_sequence;
                [DataMember]
                public Int32 Auto_Sequence
                {
                    get { return this.m_auto_sequence; }
                    set { this.m_auto_sequence = value; }

                }

                private Int32 m_detail_sequence;
                [DataMember]
                public Int32 Detail_Sequence
                {
                    get { return this.m_detail_sequence; }
                    set { this.m_detail_sequence = value; }
                }

                private string m_caption;
                [DataMember]
                public string Caption
                {
                    get { return this.m_caption; }
                    set { this.m_caption = value; }
                }

                private string m_comments;
                [DataMember]
                public string Comments
                {
                    get { return this.m_comments; }
                    set { this.m_comments = value; }

                }

                private string m_IsActive;
                [DataMember]
                public string IsActive
                {
                    get { return this.m_IsActive; }
                    set { this.m_IsActive = value; }            
                }

                private DateTime m_add_date;
                [DataMember]
                public DateTime Add_Date
                {
                    get { return this.m_add_date; }
                    set { this.m_add_date = value; }           
                }

                private DateTime m_upd_date;
                [DataMember]
                public DateTime Upd_Date
                {
                    get { return this.m_upd_date; }
                    set { this.m_upd_date = value; }
                }

                private byte[] m_photovideo;
                [DataMember]
                public byte[] PhotoVideo
                {
                    get { return this.m_photovideo; }
                    set { this.m_photovideo = value; }
                }

                private BitmapImage m_BmpLogo;
                [DataMember]
                public BitmapImage BmpLogo
                {
                    get { return m_BmpLogo; }
                    set { m_BmpLogo = value; }
                }

                private Int32 m_Height;
                [DataMember]
                public Int32 Height
                {
                    get { return m_Height; }
                    set { m_Height = value; }
                }

                private Int32 m_Width;
                [DataMember]
                public Int32 Width
                {
                    get { return m_Width; }
                    set { m_Width = value; }
                }

                private string m_filename;
                [DataMember]
                public string FileName
                {
                    get { return this.m_filename; }
                    set { this.m_filename = value; }

                }

                private string m_photovisible;
                [DataMember]
                public string PhotoVisible
                {
                    get { return this.m_photovisible; }
                    set { this.m_photovisible = value; }

                }

                private string m_videovisible;
                [DataMember]
                public string VideoVisible
                {
                    get { return this.m_videovisible; }
                    set { this.m_videovisible = value; }

                }

                private MediaElement m_VideoLogo;
                [DataMember]
                public MediaElement VideoLogo
                {
                    get { return m_VideoLogo; }
                    set { m_VideoLogo = value; }
                }


            }

      private List<GalleryList> MyCurrentPhotos;

    and below is the function where I am adding the MediaElement to the List that I want to bind.

    The storagefile comes from a Filepicker which is kind of trivial that is why I am not posting the code for the selection of the file.

     public async void AddTheFile(StorageFile MyFile ,String Caption , String Comments)
            {
                try
                {
                    string myextension = Path.GetExtension(MyFile.Name);
                    GalleryList MyTemp1 = new GalleryList();
                    MyTemp1.Auto_Sequence = 1;

                    MyTemp1.Caption = Caption;
                    MyTemp1.FileName = MyFile.Name;
                    MyTemp1.Add_Date = DateTime.Now;
                    MyTemp1.IsActive = "True";
                    MyTemp1.Upd_Date = DateTime.Now;

                    var stream = await MyFile.OpenReadAsync();

                    using (var dataReader = new DataReader(stream))
                    {
                        var bytes = new byte[stream.Size];
                        await dataReader.LoadAsync((uint)stream.Size);
                        dataReader.ReadBytes(bytes);
                        MyTemp1.PhotoVideo = bytes;

                    }
                   
                    if (MyTemp1.PhotoVideo != null)
                    {
                        switch (Path.GetExtension(MyTemp1.FileName))
                        {
                            case ".mp4":
                                MediaElement MyElement = new MediaElement();
                                var stream1 = await MyFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
                                //the stream has size.
                               MyElement.SetSource(stream1, ".mp4");
                         
                                 MyTemp1.VideoLogo = MyElement;
                                  MyTemp1.PhotoVisible = "Collapsed";
                                  MyTemp1.VideoVisible = "Visible";
                               
                                 break;
                        
                            default:
                                BitmapImage bitmapImage = new BitmapImage();
                                IRandomAccessStream stream3 = this.ConvertToRandomAccessStream(new MemoryStream(MyTemp1.PhotoVideo));
                                bitmapImage.SetSource(stream3);
                                MyTemp1.BmpLogo = bitmapImage;
                                MyTemp1.PhotoVisible = "Visible";
                                MyTemp1.VideoVisible = "Collapsed";
                                break;
                        }
                       
                    }
                    if (MyCurrentPhotos == null) MyCurrentPhotos = new List<GalleryList>();
                    MyCurrentPhotos.Add(MyTemp1);
                    this.itemPhotosListView.ItemsSource = null;
                    this.itemPhotosListView.ItemsSource = MyCurrentPhotos;

                }
                catch (Exception ex)
                {
                    //display the exception
                }
            
            }

      private IRandomAccessStream ConvertToRandomAccessStream(MemoryStream memoryStream)
            {

                var randomAccessStream = new InMemoryRandomAccessStream();
                var outputStream = randomAccessStream.GetOutputStreamAt(0);
                var wrStr = outputStream.AsStreamForWrite();
                wrStr.Write(memoryStream.ToArray(), 0, (int)memoryStream.Length);
                wrStr.Flush();
                return randomAccessStream;

            }

    The code that I'm using for the Bitmap is working. I tried to use the same code for the mediaelement . I'm talking about this

      MediaElement MyElement= new MediaElement ();
                                IRandomAccessStream stream3 = this.ConvertToRandomAccessStream(new MemoryStream(MyTemp1.PhotoVideo));
                                MyElement.SetSource(stream3 , ".mp4");
                                MyTemp1.BmpLogo = bitmapImage;
                                 MyTemp1.VideoLogo = MyElement;
                                break;

    But it didn't work either.

    The rest of the bindings ARE WORKING. I can see in my listview the caption , the comments.

    But I cannot see the mediaelement which has size , has bytes has everything.

    Do I need to write it first somewhere in a physical path and then for the source property assign the path ?

    Debugging the above code shows me that after I run the SetSource command the Myelement.Source remains null. Although I have bytes.

    Can you see if there's something wrong with my code ?

    Appreciate your help

    thank you


    • Edited by zakkar Saturday, August 10, 2013 4:37 AM
    Friday, August 9, 2013 2:52 PM
  • While I still do not understand your code completely but still the way you are creating a MediaElement in your C# code, it appears you need a ContentPresenter in XAML not a MediaElement control itself.

    <DataTemplate>
        <Grid Margin="6" x:Name="DatagridPhotosTemplate" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="80"/>
            </Grid.RowDefinitions>
            <Canvas x:Name='playbackCanvas2' Width="470"  Height="470" Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                <ContentPresenter Content="{Binding VideoLogo}" Width="470"  Height="470" Visibility= "Visible" />
                <!--<MediaElement  x:Name='playbackElement2' Source="{Binding VideoEstateLogo}" Visibility= "Visible" Width="470"  Height="470" />-->
            </Canvas>
            <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0" Width="170" >
                <TextBlock Text="{Binding Caption}" Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/>
                <TextBlock Text="{Binding FileName}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
                <TextBlock Text="{Binding Comments}" Style="{StaticResource BodyTextStyle}" MaxHeight="90"/>
            </StackPanel>
        </Grid>
    </DataTemplate>

    Second the property name in your XAML was VideoEstateLogo and in your second post in code behind it appears to be VideoLogo.

    Further, when you say bitmap works I could not see a place where you have used BmpLogo in binding. But still that is a BitmapImage (not a XAML control like Windows.UI.Xaml.Controls.Image) that is a proper source for a control like Windows.UI.Xaml.Controls.Image. But if you create MediaElement itself which is XAML control then you will need a Content Presenter.

    Last but not the least, you are not using MVVM (ViewModel to be more precise). This may lead to issues where you may update a property at runtime but that will not update UI.

    If still this does not help, then please post a complete working code in a ZIP file on your SkyDrive and leave a link here.


    -- Vishal Kaushik --

    Please 'Mark as Answer' if my post answers your question and 'Vote as Helpful' if it helps you. Happy Coding!!!

    Friday, August 9, 2013 8:27 PM
  • Hi Vishal ,

    I had removed the bitmap (Image element) because I was testing for the media element and forgot to modify my code. Sorry about that. 

    Yes you are right about the property . It's a different name.

    I will try the content Presenter right away and revert with my findings.

    thank you

    Saturday, August 10, 2013 4:36 AM
  • Hi  Vishal ,

    It didn't work. 

    FYI the code is working if I use it in a Media Element outside the listview.

    I will create a sample and upload it in the Skydrive.

    thank you


    • Edited by zakkar Saturday, August 10, 2013 5:01 AM
    Saturday, August 10, 2013 4:52 AM
  • Hi Vishal ,

    Here's a sample in the skydrive

    https://skydrive.live.com/redir?resid=1947E3F873AC5320!190&authkey=!ACgmyT-y8tguEd4

    it's the ListViewMediaElement.zip

    Appreciate your help on this.

    thank you


    • Edited by zakkar Saturday, August 10, 2013 2:19 PM
    Saturday, August 10, 2013 2:14 PM
  • Hi  Matt ,

    I have uploaded an example in the Skydrive.

    https://skydrive.live.com/redir?resid=1947E3F873AC5320!190&authkey=!ACgmyT-y8tguEd4

    Appreciate your help on this.

    thank you

    zkar

    Saturday, August 10, 2013 2:18 PM
  • Has anyone bind a MediaElement in a ListView ?

    thank you


    Monday, August 12, 2013 11:43 AM
  • I've got a crazy implementation where I got this to work.  It was more difficult than I realized.  It's not fully formed, please test this out.

    <StackPanel>
      <Button Content="Choose one or more .mp4 videos" Click="Button_Click"/>
      <ListView x:Name="MyListView">
        <ListView.ItemTemplate>
          <DataTemplate>
            <StackPanel>
              <MediaElement Width="200" Height="150" AutoPlay="True" Loaded="MediaElement_Loaded"/>
              <TextBlock Text="{Binding path}" Foreground="White"/>
            </StackPanel>
          </DataTemplate>                
        </ListView.ItemTemplate>
      </ListView>
    </StackPanel>

    public sealed partial class MainPage : Page
    {
      public MainPage()
      {
        this.InitializeComponent();
      }
    
      IReadOnlyList<StorageFile> Videos;
      private async void Button_Click(object sender, RoutedEventArgs e)
      {
        var MyFilePicker = new FileOpenPicker();
        MyFilePicker.FileTypeFilter.Add(".mp4");
        Videos = await MyFilePicker.PickMultipleFilesAsync();
        MediaElementCounter = 0;
        MyListView.ItemsSource = Videos;
      }
    
      int MediaElementCounter;
      private async void MediaElement_Loaded(object sender, RoutedEventArgs e)
      {
        MediaElement CurrentMedia = sender as MediaElement;
        var MediaStream = await Videos  [MediaElementCounter].OpenAsync(Windows.Storage.FileAccessMode.Read);
        CurrentMedia.SetSource(MediaStream, ".mp4");
        MediaElementCounter++;
      }
    }
    
    class MyMediaClass
    {
      public string MyFile { get; set; }
      public MediaElement MyMedia { get; set; }
    }


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    • Marked as answer by zakkar Thursday, August 15, 2013 6:04 AM
    Tuesday, August 13, 2013 4:12 PM
    Moderator
  • Hi Matt ,

    I will give it a try and revert.

    thank you

    Wednesday, August 14, 2013 4:45 AM
  • Hi  Matt ,

    YES it is working !!!.

    I want to ask you two more questions.

    Now I'm storing the video files as a byte array(each file is saved as a byte array) in my sqlite table.(I don't want code or something for sqlite I'm OK with that).

    1.If I want to retrieve them then I need to write them in a plysical path and then use your code ??? Do I have performance penalties ? Or Should I Just display a video picture and let the user decide if he wants to "download-retrieve-play" the video ?

    2. Is it possible to take a snapshot of the video and display the snapshot in the list view ?

    thank you Matt for your help

    Wednesday, August 14, 2013 5:08 AM
  • 1) I really can't make that decision for you, but I think that you wouldn't want multiple videos playing simultaneously.

    2) Yes, it's possible.  I don't know the code involved in it, I'm not a media expert.


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Wednesday, August 14, 2013 11:35 AM
    Moderator
  • Hi Matt ,

    Thank you for your help.

    Thursday, August 15, 2013 6:04 AM
  • I had been searching for a couple of days on how to do this. Your approach worked for me. Thanks!
    Wednesday, April 30, 2014 1:40 AM