WPF MVVM DataTemplates - 查看不更新

时间:2013-06-05 18:30:27

标签: c# wpf data-binding mvvm

我正在研究数字标牌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>

随着datacontext的更改,每个窗格中的内容从一个项目转换到下一个项目。我遇到了一个问题,即用户将相同的项目连续两次放在一个窗格中,无论是视频,图像等。发生的变化是未检测到的更改并且UI不会更新。在视频的情况下,它在第一个视频的最后一帧冻结,整个应用程序挂起。

我尝试在PlaylistItem类中执行OnPropertyChanged(“ContentItem”),尝试在我的数据模板上设置Shared =“False”,我尝试更改ContentItem对象的属性并引发PropertyChanged事件,似乎没有任何效果。我开启了对数据绑定的跟踪,看看发生了什么,这一切似乎都正常工作。当我更改ContentItem上的属性时,它会显示新项目的新哈希值,但UI上没有更改。

在PlaylistItem的TransitionableContentControl中,从一个内容项转到同一个内容项时,永远不会触发OnContentChanged覆盖。如果我用常规ContentControl交换该控件,则不做任何更改。

2 个答案:

答案 0 :(得分:1)

这里的问题是,当旧的和新的内容的.Equals为真时,ContentControl(或者更确切地说是底层的DependencyProperty框架)不会触发OnContentChanged。一种解决方法是在CoerceValue上拥有自己的依赖项属性和转换。我会通过电子邮件向您发送代码,您可以在此处发布。

答案 1 :(得分:1)

前员工的诊断是正确的。此外,除非您设法重新分配内部datacontexts,否则您的模板将不会从一开始就重新启动,正如您所注意到的那样。您必须首先将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) ;
})) ;