使用System.Windows.DependencyProperty绑定属性
注意在自定义控件中 不要设置DataContext 默认就行 否则的话我们使用定义好的自定义控件时,使用动态绑定无效
我们如果使用其他类 可以在我们自定义的UserControl内部的控件上绑定DataContext
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 { set { _isPlaying = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsPlaying")); } get => _isPlaying; } public string FormatShow { set { _formatShow = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("FormatShow")); } get => _formatShow; } public bool IsFullscreen { set { _isFullscreen = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsFullscreen")); } get => _isFullscreen; } public bool IsStart { set { _isStart = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsStart")); } get => _isStart; } public bool IsLoaded { set { _isLoaded = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsLoaded")); } get => _isLoaded; } public string Poster { set { _poster = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("poster")); } get => _poster; } public bool IsAudio { set { _isAudio = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsAudio")); } get => _isAudio; } public string VideoPath { set { _videoPath = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("VideoPath")); } get => _videoPath; } public bool IsSeekable { set { _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> <!--视频封面--> <Grid> <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="视频测试"> <Grid> <!--可以使用Binding动态绑定 如果自定义控件MyControl 设置了DataContext = xxxx则无法使用动态绑定 --> <my:MyControl MediaUrl="视频地址"></my:MyControl> </Grid> </Page>