Wpf Visual Brush Visual Binding to MediaElement

2.2k Views Asked by At

I have a question about binding to a visual brush visual. If I define it in XAML it works. If I define the the same thing programmatically then it does not work. Here is an example.

 <Window x:Class="WpfApp1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            x:Name="MyWindow"
            Title="MainWindow" Height="350" Width="525">
    <Grid >
        <Rectangle Height="299" Width="400" Stroke="Red" StrokeThickness="20" >
            <Rectangle.Fill>
                <VisualBrush TileMode="None" Stretch="UniformToFill" Visual="{Binding  ElementName=MyWindow, Path=Stuff}">
                    <!--<VisualBrush.Visual>
                            <MediaElement Source="MovingImages_2017-03-10-05-02-22.wmv" LoadedBehavior="Play" />
                        </VisualBrush.Visual>-->
                </VisualBrush>
            </Rectangle.Fill>
        </Rectangle>
    </Grid>
</Window>

I have tried the following property as a visual and a media element.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public Visual Stuff { get; set; }

        public MainWindow()
        {
            InitializeComponent();

            MediaElement me = new MediaElement();
            me.Source = new Uri("MovingImages_2017-03-10-05-02-22.wmv", UriKind.Relative);
            me.LoadedBehavior = MediaState.Play;


            this.Stuff = (Visual) me;
        }
    }
}

Edit 3. I have turned up binding errors and it is being bound. It turns up in the Live Visual Tree / Live property Explorer. It just does not show up.

Does anyone know why?

3

There are 3 best solutions below

2
avamir10 On

It seems like this is because your Stuff property does not notify it changed. You have three choices to solve this:

1) Implement the INotifyPropertyChanged interface in your MainWindow class and when setting the Stuff property raise the PropertyChanged event.

2) Define the Stuff property as a DependencyProperty which has inherent property change notifications (since your class is a DependencyObject)

3) Assign the property value before calling InitializeComponent. This will obviously work only once during initialization.

public MainWindow()
{
    Stuff = new MediaElement
    {
        Source = new Uri("MovingImages_2017-03-10-05-02-22.wmv", UriKind.Relative),
        LoadedBehavior = MediaState.Play
    };

    InitializeComponent();
}

These are the two available methods for a property to participate in the Binding game

1
avamir10 On

There seems to be an issue when binding Visuals and VisualBrushes. In this case I would suggest to side step your problem in a way which also fits better MVVM separation. Instead of binding a Visual, create the visual in XAML and bind to the Visual's Source property. Your XAML would be:

<Rectangle Height="299" Width="400" Stroke="Red" StrokeThickness="20">
        <Rectangle.Fill>
            <VisualBrush TileMode="None" Stretch="UniformToFill">
                <VisualBrush.Visual>
                        <MediaElement Source="{Binding Path=MovieUri, ElementName=MyWindow}" LoadedBehavior="Play" />
                    </VisualBrush.Visual>
            </VisualBrush>
        </Rectangle.Fill>
    </Rectangle>

And your code behind:

public Uri MovieUri { get; set; }

    public MainWindow()
    {
        MovieUri = new Uri("movie.mp4", UriKind.Relative);

        InitializeComponent();            
    }
0
Haydn On

It's not possible to use a binding to anything that contains a media element and get it to play.

A workaround is you subscribe to the view model property changed event for the object containing the media element. When it changes you add the object programmatically. Then the media element will display and play.