使用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>