wpf обновляет свойство фона ListViewItem - PullRequest
1 голос
/ 23 декабря 2008

У меня есть просмотр списка, который связан с 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 в зависимости от значения перечисления. Который обновляется на основе правил бизнес-логики. В настоящее время это работает, но только для начального отображения элемента. Когда я изменяю свойство «Status» объекта, к которому привязан listItemView, фон не обновляется. Если я удаляю объект из коллекции, меняю статус, а затем снова добавляю его в коллекцию, фон обновляется.
Я попытался создать объект IPropertyNotify и выдать событие в установщик изменения свойства status, но это не сработало.

Кто-нибудь знает, нужно ли мне что-то особенное сделать, чтобы обновить фон элемента списка. Я также открыт для других идей о том, как решить эту проблему, спасибо. вот XAML для ListView. EncoderService.Encoders - это моя ThreadSafeObservableCollection объектов Encoder.

        <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 ]

2 голосов
/ 25 декабря 2008

Проблема в том, что 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>

В этом случае, если вы реализуете INotifyPropertyChanged в Encoder и уведомляете при каждом изменении состояния, привязка должна обновиться для вас. Это также означает, что вам нужно обновить EncoderStatusToColorConverter, чтобы он принимал только тип Status.

1 голос
/ 23 декабря 2008

Вы пытались использовать 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"/>
0 голосов
/ 23 декабря 2008

Думаю, я не совсем понимаю, что может повлиять на INotifyPropertyChanged.

Итак, у меня есть ObservableCollection объектов "Кодировщик". Очевидно, что ObservableCollection является наблюдаемым, и когда я добавляю и удаляю из него что-то, он обновляется. но свойства каждого «кодировщика» не обновляются. Из того, что я понимаю, это означает, что класс Encoder должен реализовывать INotifyPropertyChanged и отправлять имя свойства в событии. Это правильное мышление? потому что на данный момент это не работает. Я хочу убедиться, что у меня есть правильная теория, прежде чем публиковать больше кода.

спасибо

0 голосов
/ 23 декабря 2008

Мне нравится этот подход, и я собираюсь попытаться его продолжить, но единственная проблема, которую я сразу вижу, состоит в том, что я использую GridView, потому что я показываю табличные данные. Мне нравятся заголовки столбцов. Но я думаю, что могу найти способ обойти это. Возможно, я просто добавлю свои заголовки столбцов вручную.

Как ListItem получает уведомление, что он должен обновить свой шаблон данных? это происходит каждый раз, когда он получает событие PropertyChanged для любого из своих ограниченных элементов?

...