2013-11-20 1 views
2

Я надеюсь, что некоторые из вас, возможно, столкнулись с проблемой и могут объяснить мне, что здесь происходит. Я пробовал несколько исправлений (в мире MVVM :), который не помог, и я хотел бы понять проблему, прежде чем применять некоторые хаки, если необходимо,Цвет переднего плана не обновляется в выбранной строке в WPF DataGrid

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

Это работает отлично, но иногда (действительно не могу сказать, когда и почему) это не так. Это может произойти примерно через 20 минут после правильной работы окна приложения, но не активно (пользователи смотрят на экран, но не взаимодействуют с ним).

Одна важная информация заключается в том, что всякий раз, когда пользователь нажимает на строку, цвета сразу фиксируются.

Кроме того, может быть, стоит заметить, что целые цвета строк не обновлять и цифры правильны ....

Всех обновлений в собственность сделаны с BeginInvoke на диспетчере и может произойти очень часто (около 20 раз в секунду).

Wrong colour from the foreground binding

Любые идеи приветствуются.

(ранее я думал, что это может быть виртуализация, но это не помогло)

<DataGrid 
    ItemsSource="{Binding Items}" 
    IsReadOnly="True" 
    AlternatingRowBackground="#E5E5E5" 
    EnableRowVirtualization="False" 
    VirtualizingStackPanel.IsVirtualizing="False" 
    VirtualizingStackPanel.VirtualizationMode="Standard"> 

сетки данных столбца

<DataGridTextColumn Binding="{Binding A}" Header="A" Width="85" FontWeight="Bold"> 
    <DataGridTextColumn.CellStyle> 
    <Style TargetType="DataGridCell" BasedOn="{StaticResource NotSelectableCellStyle}"> 
     <Setter Property="Block.TextAlignment" Value="Right"/> 
     <Setter Property="Foreground" Value="{Binding A, Converter={StaticResource colorConverter}}"/> 
    </Style> 
    </DataGridTextColumn.CellStyle> 
</DataGridTextColumn> 

Преобразователь

public class NegativePositiveColorConverter : IValueConverter 
{ 
    private static readonly Brush negativeBrush; 

    private static readonly Brush positiveBrush; 

    static NegativePositiveColorConverter() 
    { 
     negativeBrush = new SolidColorBrush(Colors.Red); 
     positiveBrush = new SolidColorBrush(Colors.Green); 
     negativeBrush.Freeze(); 
     positiveBrush.Freeze(); 
    } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     decimal? decimalValue = value as decimal?; 
     if (!decimalValue.HasValue) 
     { 
      return Binding.DoNothing; 
     } 

     if (decimalValue < 0) 
     { 
      return negativeBrush; 
     } 

     return positiveBrush; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 

Источник свойство объекта

public decimal? A 
    { 
     get 
     { 
      return this.a; 
     } 

     set 
     {          
      if (this.a!= value) 
      { 
       this.a= value; 
       OnPropertyChanged("A"); 
      } 
     } 
    } 

Cell Style (а не важно)

<Style TargetType="DataGridCell" x:Key="NotSelectableCellStyle" BasedOn="{StaticResource {x:Type DataGridCell}}"> 
    <Style.Triggers> 
     <Trigger Property="IsSelected" Value="True"> 
      <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Background}"/> 
     </Trigger> 
    </Style.Triggers> 
    <Setter Property="Background" Value="{StaticResource EditableBrush}"/> 
    <Setter Property="Padding" Value="3,0,3,0" /> 
    <Setter Property="Template" Value="{StaticResource NotSelectableDataGridCellTemplate}"/> 
</Style> 

<ControlTemplate x:Key="NotSelectableDataGridCellTemplate" TargetType="{x:Type DataGridCell}" > 
    <Grid> 
     <Border Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> 
      <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
     </Border>    
    </Grid> 
</ControlTemplate> 
+1

В любом случае, я бы сначала добавил некоторый журнал/трассировку как для метода 'Convert', так и для' A' setter, и будет записывать все десятичные значения, которые вводят оба метода, чтобы увидеть, является ли 'Convert' вызывается или нет, когда свойство изменяется. Вам понадобятся время регистрации, идентификаторы потоков и значения. – Groo

+0

Обратите внимание, что источник привязки для числа и цвета тот же, что и свойство PropertyChanged должно быть вызвано для изменения номера. –

+0

Попробуйте DataTrigger вместо конвертера. – Bijan

ответ

2

ОК, я нашел эту проблему благодаря (кажется очевидным, но по некоторым причинам я не по этому пути раньше) предложение от @Groo. Я только что добавил много записей в преобразователях и установщиках свойств и заметил, что для одного из строк преобразователи никогда не выполняются, если я не нажму на поверхность сетки.

Это произошло для строки, представляющей выбранный элемент (и каждый раз это была другая строка, в зависимости от того, какой из них был добавлен первым).

Потому что мой стиль не отображает выделение (см. Раздел «Стиль ячейки (а это не важно)» часть моего вопроса) Я бы не заметил ничего особенного в неудачной строке.

Я считаю, что одним из возможных исправлений является установка SelectedItem в null при каждом выборе элемента. Почему передний план не обновляется, когда элемент выбран. Я не уверен.

+0

Это немного взломанный, но он работает, если вы добавите (дублируете) ту же самую привязку переднего плана внутри триггера IsSelected? – Groo

+0

Спасибо @Groo, я могу попробовать вещь с помощью триггера. После нескольких экспериментов я понял, что любой выбор не позволяет обновлять цвета переднего плана (я мог бы даже не допустить, чтобы вся сетка обновлялась передними цветами, когда я использовал режим расширенного выбора и сдвигал все. Я добавил IsHitTestVisible = false для стиля ячейки и теперь единственный способ разбить его - это остановить табуляцию в сетке и выбрать строку. –

+0

IsSynchronizedWithCurrentItem = «False» решил проблему. –

Смежные вопросы