Reputation: 147
I have a MainView where I'm using a component I created called VideoPlayer. VideoPlayer is a Grid that has a MediaElement as well as some buttons and a slider to control video playback.
I'm trying to set the path of the video to be played in MainView by binding a property in VideoPlayer to a property in MainView.
The relevant parts of the code are below:
Snippet from VideoPlayer.xaml:
<MediaElement
Name="MediaElement"
Grid.Row="0"
LoadedBehavior="Manual"
Stretch="Uniform"
Source="{Binding VideoLocation}" />
Snippet from VideoPlayer.xaml.cs:
public string VideoLocation
{
get { return (string)GetValue(VideoLocationProperty); }
set { SetValue(VideoLocationProperty, value); }
}
public static readonly DependencyProperty VideoLocationProperty
= DependencyProperty.Register("VideoLocation", typeof(string), typeof(VideoPlayer), new PropertyMetadata(null));
VideoPlayer is used in MainView.xaml, which is following MVVM:
<ReuseableComponents:VideoPlayer VideoLocation="{Binding VideoPath}"/>
This is the bound property, VideoPath, in MainViewModel.cs:
private string _videoPath;
public string VideoPath
{
get => _videoPath;
set => SetProperty(ref _videoPath, value);
}
If I remove the VideoLocation binding and hard code a path in MainView.xaml, the video will play just fine:
<ReuseableComponents:VideoPlayer VideoLocation="C:\Movies\FightClub.mp4"/>
So, I think the issue is with the MainView binding and not the VideoPlayer binding.
All of my other property bindings in MainView work, and they all follow this pattern:
<ComponentName PropertyName="{Binding ViewModelPropertyName}">
where ViewModelPropertyName is defined in MainView with a backing field and the setter calls SetProperty()
EDIT
The error I made was: in the constructor for VideoPlayer I had a line DataContext = this;
I think I saw it in some tutorial somewhere. Anyway as per @Magnus advice I removed the line and changed VideoPlayer.xaml to
<UserControl x:Name="TheControl" ...>
<Grid DataContext={Binding ElementName=TheControl} ...>
...
</Grid>
</UserControl>
Where previously the UserControl didn't have the name property set and the Grid didn't have the DataContext property set.
Upvotes: 0
Views: 643
Reputation: 546
The problem might be that you are setting the DataContext of your VideoPlayer UserControl to itself on the top level. That means you override the MainView DataContext that the control should inherit, i.e., this binding:
<ReuseableComponents:VideoPlayer VideoLocation="{Binding VideoPath}"/>
tries to bind to the VideoPlayer control instead of the MainView DataContext.
You could instead set the internal DataContext of your VideoPlayer on a contained element, something like this:
<UserControl x:Name="TheControl" ...>
<Grid DataContext={Binding ElementName=TheControl} ...>
...
</Grid>
</UserControl>
Upvotes: 1
Reputation: 16119
The Binding is being done relative to your control's DataContext, which you probably haven't set. You need to set it relative to the control instead. Give your control a name like this:
<UserControl x:Class="YourApp.YourUserControl"
... etc ...
x:Name="_this">
And then bind to that directly:
Source="{Binding ElementName=_this, Path=VideoLocation}"
Alternatively you can also use a RelativeSource binding with AncestorType set to your user control type.
Upvotes: 0