WPF MVVM DataTemplates -视图未更新
本文关键字:更新 视图 MVVM DataTemplates WPF | 更新日期: 2023-09-27 18:17:00
我正在开发一个数字标牌WPF应用程序,基本结构设置如下:
我有一个视图,其中有一个网格绑定到一个播放列表对象。播放列表包含窗格,窗格包含播放列表项,每个播放列表项包含一个内容项。我使用DataTemplates为每个片段构建视图,例如
<!-- This template represents a single content pane, no real display here, just empty space with a height and width -->
<DataTemplate DataType="{x:Type entities:ContentPane}">
<ContentControl
Content="{Binding CurrentPlaylistItem, Mode=OneWay}"
Height="{Binding Height, Mode=OneTime}"
Width="{Binding Width, Mode=OneTime}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
/>
</DataTemplate>
<!-- This is a playlist item which is contained within a ContentPane.
This also has no real display, just a placeholder for the content item, and will likely contain some transition information-->
<DataTemplate DataType="{x:Type entities:PlaylistItem}">
<inf:TransitionableContentControl Content="{Binding ContentItem}"></inf:TransitionableContentControl>
</DataTemplate>
<!-- image item template
the path can be any valid uri e.g. http://... or file://... -->
<DataTemplate DataType="{x:Type contentTypes:ImageContentType}">
<Grid Background="Transparent" x:Name="ImageType">
<Image Source="{Binding Bitmap, Mode=OneTime}"></Image>
<inf:BusinessAd
ContainerHeight="{Binding ImageHeight, Mode=OneTime}"
ContainerWidth="{Binding ImageWidth, Mode=OneTime}"
Visibility="{Binding AdText, Converter={StaticResource _VisibilityConverter}, Mode=OneWay}"
Text="{Binding AdText.Text, Mode=OneTime}"
AdFontSize="{Binding AdText.TextStyle.FontSize}"
AdFontFamily="{Binding AdText.TextStyle.FontFamily}">
<ContentControl
Content="{Binding AdText, Mode=OneTime}"
ContentTemplate="{StaticResource BusinessAdTextTemplate}">
</ContentControl>
</inf:BusinessAd>
</Grid>
</DataTemplate>
随着数据上下文的变化,每个窗格中的内容从一个项转换到下一个项。我遇到了一个问题,用户在一个窗格中连续放置两次相同的项目,无论是视频,图像等。发生的情况是,更改没有被检测到,UI也没有更新。在视频的情况下,它在第一个视频的最后一帧冻结,整个应用程序挂起。
我试过在PlaylistItem类中做一个OnPropertyChanged("ContentItem"),试着在我的数据模板上设置Shared="False",我试着改变ContentItem对象的属性并引发PropertyChanged事件,似乎没有任何作用。我打开了对数据绑定的跟踪,看看发生了什么,一切似乎都工作正常。当我更改ContentItem的属性时,它会显示新项目的新散列,但UI上没有更改。
在PlaylistItem中的TransitionableContentControl中,当从一个内容项到同一个内容项时,OnContentChanged覆盖永远不会被击中。如果我把那个控件换成常规的ContentControl,没有变化
前雇员的诊断是正确的。此外,如您所注意到的,除非您设法重新分配内部数据上下文,否则您的模板不会从头开始重新启动。你将不得不分配你的CurrentPlaylistItem
到一些默认的空项目,首先重置所有的东西。为了避免竞争和讨厌的闪烁,在比UI渲染更高的调度程序优先级上进行。试试这个:
// CurrentPlaylistItem = pli ; -- not good
Application.Current.Dispatcher.Invoke (new Action (() =>
{
// clear item
// null doesn't work, because TransitionableContentControl's
// inner ContentControl would be empty and the brush created
// from it would be a null brush (no visual effect)
CurrentPlaylistItem = new PlaylistItem () ;
this.OnPropertyChanged ("CurrentPlaylistItem") ;
Application.Current.Dispatcher.Invoke (new Action (() =>
{
// set new item, possibly same as old item
// but WPF will have forgotten that because
// data bindings caused by the assignment above
// have already been queued at the same DataBind
// level and will execute before this assignment
CurrentPlaylistItem = pli ;
this.OnPropertyChanged ("CurrentPlaylistItem") ;
}), DispatcherPriority.DataBind) ;
})) ;
这里的问题是ContentControl(或更确切地说底层DependencyProperty框架)不触发OnContentChanged时。equals为真新旧内容。一种解决方法是在CoerceValue上拥有自己的依赖属性和转换。我会把代码发邮件给你,你可以发到这里