C# 如何设置由第三方计时器更新的DependencyProperty?
我正在玩Vlc.DotNet库(Nuget:Vlc.DotNet/)。它实际上是一个围绕libvlc.dll的WinForms包装器,带有一个非常粗略的WPF控件实现,它只将WinForms控件包装在HwndHost中:C# 如何设置由第三方计时器更新的DependencyProperty?,c#,.net,wpf,C#,.net,Wpf,我正在玩Vlc.DotNet库(Nuget:Vlc.DotNet/)。它实际上是一个围绕libvlc.dll的WinForms包装器,带有一个非常粗略的WPF控件实现,它只将WinForms控件包装在HwndHost中: //WPF control class public class VlcControl : HwndHost { //The WPF control has a property called MediaPlayer, //which is an instan
//WPF control class
public class VlcControl : HwndHost
{
//The WPF control has a property called MediaPlayer,
//which is an instance of Forms.VlcControl
public Forms.VlcControl MediaPlayer { get; private set; }
//WPF control constructor
public VlcControl()
{
MediaPlayer = new Forms.VlcControl();
}
//BuildWindowCore and DestroyWindowCore methods omitted for brevity
}
这意味着,如果我想绑定到任何东西,我需要跳过一些环。如果我的WPF控件实例名为MyWpfControl,我需要通过MyWpfVlcControl.MediaPlayer来解决所有问题。[SomeMethod/SomeProperty]。我想向WPF控件添加一些DependencyProperties以使绑定更容易。我在计时器上更新的属性以及由备份dll和用户通过WPF控件设置的属性方面遇到问题
WinForms player具有long类型的Time属性,表示已用媒体时间(以毫秒为单位)。它还有一个名为TimeChanged的事件,该事件在播放过程中不断激发,更新已用的媒体时间
我已为TimeChanged事件向WPF控件添加了一个事件处理程序:
//WPF control constructor
public VlcControl()
{
MediaPlayer = new Forms.VlcControl();
MediaPlayer.TimeChanged += OnTimeChangedInternal;
}
private void OnTimeChangedInternal(object sender, VlcMediaPlayerTimeChangedEventArgs e)
{
Time = e.NewTime;
}
如果我在WPF控件中设置DependencyProperty来包装时间,它看起来如下所示:
// Using a DependencyProperty as the backing store for Time. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TimeProperty =
DependencyProperty.Register("Time", typeof(long), typeof(VlcControl), new FrameworkPropertyMetadata(0L, new PropertyChangedCallback(OnTimeChanged)));
/// <summary>
/// Sets and gets the Time property.
/// </summary>
public long Time
{
get
{
return (long)this.GetValue(TimeProperty);
}
set
{
this.Dispatcher.Invoke((Action)(() =>
{
this.SetValue(TimeProperty, value);
}));
}
}
private static void OnTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//Tried this - bad idea!
//MediaPlayer.Time = (long)e.NewValue;
}
//使用DependencyProperty作为时间的后备存储。这将启用动画、样式、绑定等。。。
公共静态只读DependencyProperty TimeProperty=
DependencyProperty.Register(“时间”、typeof(长)、typeof(VlcControl)、new FrameworkPropertyMetadata(0L、new PropertyChangedCallback(OnTimeChanged));
///
///设置并获取时间属性。
///
公众长期
{
得到
{
返回(长)this.GetValue(TimeProperty);
}
设置
{
this.Dispatcher.Invoke((操作)(()=>
{
this.SetValue(TimeProperty,value);
}));
}
}
私有静态void OnTimeChanged(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
//尝试过这个-坏主意!
//MediaPlayer.Time=(long)e.NewValue;
}
时间从libvlc.dll->WinForms->WPF漂亮地更新。不幸的是,如果我想从WPF控件设置MediaPlayer.Time属性,我需要将上面的注释行合并到OnTimeChanged中。当这是未注释的,并且MediaPlayer更新时间属性(与WPF控件相反)时,它会进入一个无限循环:TimeChanged->SetTime->TimeChanged->SetTime->
有没有更好的方法来实现这一点?我可以在某个地方添加一个参数来指示时间是从WPF还是从WinForms代码设置的吗?您可以尝试实现一种类型的指示器来防止无限循环。比如:
bool isUpdating = false;
private static void OnTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!isUpdating)
{
isUpdating = true;
MediaPlayer.Time = (long)e.NewValue;
isUpdating = false;
}
}
只是想澄清一下VlcControl和Forms.VlcControl是不同的类,对吗?让人很难理解什么是什么。是的,VlcControl和Forms.VlcControl是不同的类。我会把这个问题快速地看一遍,看看是否能把事情弄清楚一点。不过我想这会给你一次往返的机会。一开始我也在想同样的事情。这就是我最后的想法。我必须将我的指示符字段声明为static,才能将其放入static OnTimeChanged方法的作用域中。在
OnTimeChanged
中,您有一个引发该方法的对象(在上面的代码中称为d
)。因此,您可以将其强制转换为VlcControl
,并在控件上使用公共属性,而不是静态标志。