1

我有一个绑定到 ThreadSafeObservableCollection 的列表视图。这些项目中的每一个的背景都设置为一个通过颜色转换器运行的枚举,这是这两个设置的代码。

<UserControl.Resources>
    <EncoderView:EncoderStatusToColorConverter x:Key="ColorConverter"/>
    <Style x:Key="ItemContStyle" TargetType="{x:Type ListViewItem}">
        <Setter Property="Background" Value="{Binding Converter={StaticResource ColorConverter}}" />
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    </Style>
</UserControl.Resources>

我想要发生的是 listviewItem 的背景颜色将根据枚举值从 Red - Yellow - Green 变化。根据业务逻辑规则更新。这目前有效,但仅适用于项目的初始显示。当我更改 listItemView 绑定到的对象的“状态”属性时,背景不会更新。如果我从集合中删除对象,更改状态,然后再次将其添加到集合中,则背景会更新。
我已经尝试制作对象 IPropertyNotify,并在状态属性更改设置器上抛出事件,但这不起作用。

有谁知道我是否需要做一些特别的事情才能更新列表视图项目的背景。我也对如何解决这个问题的其他想法持开放态度,谢谢。这是 ListView 的 XAML。EncoderService.Encoders 是我的 Encoder 对象的 ThreadSafeObservableCollection。

        <ListView  AutomationProperties.AutomationId="FinishScreen"  
                   ItemsSource="{Binding Path=EncoderService.Encoders}" 
                   x:Name="DataListView" Grid.RowSpan="1" Grid.Row="1" Margin="5"
                   ItemContainerStyle="{StaticResource ItemContStyle}"
                   Background="Azure">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="MAC">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <ContentControl Content="{Binding Path=MAC}" ToolTip="{Binding Path=MAC}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="IDF">...
4

4 回答 4

2

问题是 Binding to Background 占用了整个 Encoder 对象,除非您删除并添加它,否则它不会改变。即使 Encoder 实现了 INotifyPropertyChanged,Binding 仍然在查看整个 Encoder 对象,并且无法知道 Encoder 的哪些属性与您的 EncoderStatusToColorConverter 相关,因此它不会自行更新。

您的解决方案是将背景绑定的范围缩小到仅与 EncoderStatusToColorConverter 相关的属性(或属性)。绑定路径中的任何属性都将被监视更新。因此,例如,如果您只需要状态:

<Style x:Key="ItemContStyle" TargetType="{x:Type ListViewItem}">
    <Setter Property="Background" Value="{Binding Path=Status, Converter={StaticResource ColorConverter}}" />
    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>

在这种情况下,如果您在 Encoder 上实现 INotifyPropertyChanged 并在 Status 更改时通知,则 Binding 应该为您更新。这也意味着您需要更新您的 EncoderStatusToColorConverter,使其仅采用 Status 类型。

于 2008-12-25T20:07:32.253 回答
1

您是否尝试过使用 DataTemplateSelector?我用它来更改用于 ListBoxItem 的模板,这基本上只是根据属性更改前景色。我没有尝试过你正在做的场景,在页面加载后数据发生变化,但我不明白为什么它不起作用。

我有这堂课:

public class UniqueWordDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item != null && item is WordScore)
        {
            WordScore word = item as WordScore;

            FrameworkElement elem = container as FrameworkElement;

            if (word.IsUnique)
                return
                    elem.FindResource("UniqueWordListTemplate") as DataTemplate;
            else
                return
                    elem.FindResource("WordListTemplate") as DataTemplate;
        }

        return null;
    }
}

在我控制的资源中,我有这一行:

    <UserControl.Resources>
    ...
    <my:UniqueWordDataTemplateSelector x:Key="myDataTemplateSelector"/>

我也有我的两个模板在这里:

    <DataTemplate x:Key="WordListTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="210" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding Path=Word}" Background="{x:Null}" Foreground="White"/>
            <TextBlock Text="{Binding Path=Score}" Background="{x:Null}" Foreground="White"/>
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="UniqueWordListTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="210" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding Path=Word}" Background="{x:Null}" Foreground="Gold"/>
            <TextBlock Text="{Binding Path=Score}" Background="{x:Null}" Foreground="White"/>
        </Grid>
    </DataTemplate>

然后我将以下内容用于我的 ListBox:

   <ListBox x:Name="PlayerList2" ItemTemplateSelector="{DynamicResource myDataTemplateSelector}" IsSynchronizedWithCurrentItem="True" Background="#FF252525"/>
于 2008-12-23T17:45:06.863 回答
0

我喜欢这种方法,并且我将尝试说服它,但我立即看到的唯一问题是我正在使用 GridView,因为我正在显示表格数据。我喜欢列标题。但我想我可以找到解决办法。我可能只是手动放入我自己的列标题。

ListItem 如何得到通知它应该更新它的数据模板?每次在其任何有界项上收到 PropertyChanged 事件时都会发生这种情况吗?

于 2008-12-23T18:06:23.277 回答
0

我想我可能对必须实施 INotifyPropertyChanged 的​​内容感到困惑。

所以我有一个“编码器”对象的 ObservableCollection。ObservableCollection 显然是可观察的,当我从中添加和删除内容时,它会更新。但是每个“编码器”的属性都没有被更新。据我了解,这意味着“编码器”类必须实现 INotifyPropertyChanged,并在事件中发送属性的名称。这是正确的想法吗?因为目前它不起作用。在发布更多代码之前,我想确保我的理论是正确的。

谢谢

于 2008-12-23T20:34:53.057 回答