需要继承System.Windows.Controls.UserControl类
使用System.Windows.DependencyProperty绑定属性
注意在自定义控件中 不要设置DataContext 默认就行 否则的话我们使用定义好的自定义控件时,使用动态绑定无效
我们如果使用其他类 可以在我们自定义的UserControl内部的控件上绑定DataContext
MyControl后台类
namespace MyApp.Component
public partial class MyControl : UserControl
// 这里控件属性的定义也可以放到一个实体类中 实体类需要继承DependencyObject
// 在这里实例化这个实体类,并在绑定(SetBinding)的时候 把Source 设置为这个实体类的对象
// 建议直接放到自定义控件类内部,因为这些字段需要提供给使用者传入
// DependencyProperty暂时不知道怎么回事,无法在页面绑定 只能在在后台使用SetBinding绑定
// 页面上绑定数据 可以新建一个实体类 实现INotifyPropertyChanged
private static readonly VideoData VideoData = new VideoData();
public string MediaUrl
set => SetValue(MediaUrlProperty, value);
get => (string)GetValue(MediaUrlProperty);
public string Poster
set => SetValue(PosterProperty, value);
get => (string)GetValue(PosterProperty);
public bool IsAudio
set => SetValue(IsAudioProperty, value);
get => (bool)GetValue(IsAudioProperty);
public static readonly DependencyProperty MediaUrlProperty = DependencyProperty.Register("MediaUrl", typeof(string), typeof(VideoControl),
new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.None, (sender, args) =>
if (args.NewValue != null)
//MediaUrl值改变
((MyControl)sender).VlcControl.SourceProvider.MediaPlayer.Play(new Uri(args.NewValue.ToString()), new string[] { });
public static readonly DependencyProperty PosterProperty = DependencyProperty.Register(nameof(Poster), typeof(string), typeof(VideoControl),
new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.None, (sender, args) =>
if (args.NewValue != null)
VideoData.Poster = args.NewValue as string;
public static readonly DependencyProperty IsAudioProperty = DependencyProperty.Register(nameof(IsAudio), typeof(bool), typeof(VideoControl),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.None, (sender, args) =>
//bool 只能取值true和false 所以这里默认值不能设置为空
//这里默认值为false 所以这里初始化时控件传递过来的是false 这里就不执行了
//所以需要对我们需要控制的属性设置好默认值,防止属性被其他页面更改为true,另一个页面初始化时传递的是false
//这里就不会被执行导致实际和预期的属性值不一样,导致程序出现bug
//注意这里VideoData定义为静态的
//注意这里需要注意 VideoData.IsAudio 初始化时一定要是false
VideoData.IsAudio = (bool)args.NewValue;
public MyControl()
//!DesignerProperties.GetIsInDesignMode(this)
//为了处理引入该控件预览问题
if (DesignerProperties.GetIsInDesignMode(this))
//设计模式什么也不处理 主要处理预览出错问题
//这么处理的话不影响引入该控件页面其他位置的预览
//就是当前控件被引入时预览时不显示 只显示一个框框
return;
//运行模式才进行处理
InitializeComponent();
//在后台绑定 (我在前台页面绑定不生效,不知道什么原因,可能时我的使用姿势不对)
//这里把视频的地址绑定到Tag上 在回调地方把控件的视频地址修改了
//VlcControl.SetBinding(Vlc.DotNet.Wpf.VlcControl.TagProperty, new Binding("MediaUrl") { Source = this });
//nameof(MediaUrl) 等同于 "MediaUrl"
VlcControl.SetBinding(Vlc.DotNet.Wpf.VlcControl.TagProperty, new Binding(nameof(MediaUrl)) { Source = this });
//注意不要设置 DataContext = VideoData 否则DependencyProperty 值改变事件无法生效
//VideoData 是静态的每次实例化时需要设置默认值 和 IsAudioProperty 的默认值对应
//否则可能出现问题
VideoData.IsAudio = false;
RootLayout.DataContext = VideoData
private void UserControl_Loaded(object sender, RoutedEventArgs e)
//加载初始化
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
//结束清理资源
VideoData类
namespace MyApp.custom
internal class VideoData : INotifyPropertyChanged
private bool _isPlaying;
private string _formatShow;
private bool _isFullscreen;
private bool _isStart;
private bool _isLoaded;
private string _poster; // 视频封面图
private bool _isAudio;
private string _videoPath; //当前正在播放的音视频地址
private bool _isSeekable;
public bool IsPlaying
_isPlaying = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsPlaying"));
get => _isPlaying;
public string FormatShow
_formatShow = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("FormatShow"));
get => _formatShow;
public bool IsFullscreen
_isFullscreen = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsFullscreen"));
get => _isFullscreen;
public bool IsStart
_isStart = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsStart"));
get => _isStart;
public bool IsLoaded
_isLoaded = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsLoaded"));
get => _isLoaded;
public string Poster
_poster = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("poster"));
get => _poster;
public bool IsAudio
_isAudio = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsAudio"));
get => _isAudio;
public string VideoPath
_videoPath = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("VideoPath"));
get => _videoPath;
public bool IsSeekable
_isSeekable = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsSeekable"));
get => _isSeekable;
public event PropertyChangedEventHandler PropertyChanged;
MyControl.xaml 前台页面
<UserControl x:Class="MyApp.custom.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyApp"
xmlns:res="clr-namespace:MyApp.Properties"
xmlns:vlc="clr-namespace:Vlc.DotNet.Wpf;assembly=Vlc.DotNet.Wpf"
mc:Ignorable="d"
Loaded="UserControl_Loaded"
Unloaded="UserControl_Unloaded"
d:DesignHeight="675" d:DesignWidth="1200">
<Grid x:Name="RootLayout">
<vlc:VlcControl Name="VlcControl"></vlc:VlcControl>
<!--视频封面-->
<Image Stretch="Fill" Name="PosterImage">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="{Binding Poster}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Poster}" Value="{x:Null}">
<Setter Property="Source" Value="{x:Null}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Grid>
</Grid>
</UserControl>
使用MyControl
<Page x:Class="MyApp.ui.VideoPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyApp"
xmlns:res="clr-namespace:MyApp.Properties"
xmlns:my="clr-namespace:MyApp.custom"
mc:Ignorable="d"
Loaded="Page_Loaded"
d:DesignHeight="1080" d:DesignWidth="1920"
Title="视频测试">
<!--可以使用Binding动态绑定
如果自定义控件MyControl 设置了DataContext = xxxx则无法使用动态绑定
<my:MyControl MediaUrl="视频地址"></my:MyControl>
</Grid>
</Page>