我相信这是因为 MediaElement 上这些属性的更改事件是 RoutedEventHandler 类型,而不是 RoutedPropertyChangedEventHandler 类型(就像 Slider 上的 ValueChanged 事件一样)。初始元素绑定工作正常,因为 DownloadProgress 确实是一个 DependencyProperty,它只是永远不会收到任何类型的属性更改通知,因此它永远不会更新。
这意味着您几乎无法以某种方式关闭 DownloadProgressChanged 事件。如果您真的想避免使用代码隐藏,我建议您使用某种 Blend TargettedTriggerAction。仍然会有一小部分代码,但它会在 XAML 中以声明方式进行标记,至少它是可重用的,并且在您的代码隐藏之外。
像这样的东西可能会起作用(我也在处理转换为 % 和十进制格式):
[TypeConstraint(typeof(MediaElement))]
public class UpdateDownloadProgressBehavior : TargetedTriggerAction<TextBlock>
{
protected override void Invoke(object parameter)
{
MediaElement mediaElement = (MediaElement)this.AssociatedObject;
this.Target.Text = (mediaElement.DownloadProgress * 100).ToString("0.0");
}
}
然后,您将调用它作为 XAML 中的 DownloadProgressChanged EventTrigger 的操作,并将您要更新的 TextBlock 作为目标。
<MediaElement x:Name="MyMediaElement">
<i:Interaction.Triggers>
<i:EventTrigger EventName="DownloadProgressChanged">
<local:UpdateDownloadProgressBehavior TargetName="MyTextBlock"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</MediaElement>
我不确定这对你来说是否比直接在代码隐藏中连接它更干净,但我个人更喜欢它。我能想到的唯一其他解决方案是某种 BindingConduit 帮助器,如此处所述,它可以实现 INotifyPropertyChanged 并处理通知,但我不完全确定将它与 MediaElement 一起使用会涉及什么。