WpfToolkit DataGrid: выделение измененных строк

2

Есть ли способ выделить все измененные строки в DataGrid? Поскольку сетка привязана к System.Data.DataTable, я решил, что могу связать цвет каждой строки с ним в RowState (пример ниже), но это, похоже, не работает.

Любые идеи?

xmlns:data="clr-namespace:System.Data;assembly=System.Data"

<Style x:Key="DataGridRowStyle" TargetType="{x:Type toolkit:DataGridRow}">
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="true">
            <Setter Property="Background" Value="Blue" />
        </Trigger>
        <DataTrigger Binding="{Binding RowState}" Value="{x:Static data:DataRowState.Modified}">
            <Setter Property="Background" Value="LightYellow" />
        </DataTrigger>
    </Style.Triggers>
</Style>
Теги:
wpf
wpfdatagrid
wpftoolkit

3 ответа

4
Лучший ответ
<DataGrid.RowStyle> 
  <Style TargetType="DataGridRow"> 
    <Style.Triggers> 
        <DataTrigger Binding="{Binding RowState}" Value="{x:Static data:DataRowState.Modified}"> 
            <Setter Property="Background" Value="LightYellow" />            
        </DataTrigger> 
    </Style.Triggers> 
  </Style> 
</DataGrid.RowStyle> 

Обновление
После того, как вы разместили также свой xaml, очевидно, что проблема не найдена в xaml. Я коротко посмотрел на msdn для класса DataTable, и я не вижу механизма, позволяющего WPF обнаруживать изменения RowState -property. Поэтому прямая привязка к этому свойству не даст вам надежных результатов.
Кажется, что вам нужно обернуть элементы данных. Я рекомендую сделать ViewModel для элементов и добавить свойство, которое говорит, изменила ли строка с уведомлением об изменении (INotifyPropertyChanged или DP) и привязана к этому свойству. Разумеется, будут и другие альтернативы, но IMO, создающая VM для каждого элемента, в большинстве случаев является лучшим решением.

  • 0
    Это работает для вас? Я не вижу, как это отличается от моего. Я обновил вопрос, кстати.
  • 1
    @Phil: я обновил свой ответ.
2

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

  • Добавьте фиктивный столбец ModifiedDate в ваш DataTable (или если вам не нужна дата, просто добавьте фиктивный столбец для указания строки).
  • Добавьте DataTrigger в XAML, ссылаясь на столбец ModifiedDate и нужное форматирование.
  • Добавьте DataTrigger в XAML, ссылаясь на RowState (это будет заботиться только о добавках и неизмененном, так что это еще одно событие, о котором нужно беспокоиться).
  • Добавить событие RowChanged в ваш набор данных ADO.Net, который заполняет что-то в вашем столбце ModifiedDate (должен соответствовать вашему первому DataTrigger).
  • В вашем сохраненном событии, которое подталкивает данные к вашей базе данных, закройте свой фиктивный столбец ModifiedDate в конце (где RowState = неизменен (ВАЖНО: Обязательно проверяйте строку rowstate, чтобы убедиться, что во время сохранения не было ошибок.

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

1

INotifyPropertyChanged не является единственным интерфейсом, который может использовать привязка WPF для уведомления об изменении, это просто тот, к которому мы больше всего привыкли. Поскольку Bea Stollnitz пишет, ADO DataView реализует IBindingList, который реализует уведомление об изменении, поднимая ListChanged, когда список или элемент в он изменяется.

Это предлагает способ получить то, что вы хотите, хотя я не пробовал его видеть, как это работает. Вы можете получить класс из DataView, который прослушивает событие DataTable.RowChanged и поднимает ListChanged, если строка находится в представлении и его RowState изменен.

Вы не сможете создать экземпляр нового DataView в XAML без использования кода или реализации модели представления, так как если вы просто привяжетесь к DataTable, он создаст нормальный DataView. Но вы также можете исправить это: subclass DataTable и переопределить GetDefaultView, чтобы он возвращал экземпляр вашего нового DataView, а затем подкласс DataSet и переопределял Tables, чтобы вернуть экземпляр вашего нового DataTable. (Ни один из этих классов, кажется, не запечатан, слава богу.)

Edit

Конечно, это не так просто. Список, который DataView предоставляет, представляет собой набор объектов DataRowView. DataRowView реализует INotifyPropertyChanged. Я думаю, что WPF использует интерфейс IBindingList на DataView для уведомления об изменении коллекции и прослушивает PropertyChanged на DataRowView, хотя, честно говоря, мне нужно было бы копать еще немного, чтобы быть уверенным.

DataRowView вызывает только PropertyChanged, когда изменяется значение столбца в его строке. Я не вижу никакого способа вносить уведомление об изменении для других свойств в него без подкласса DataRowView, и, хотя это возможно в принципе, я не вижу прямого способа подкласса DataView для создания этих новых DataRowView объекты.

  • 0
    +1: интересно, спасибо за информацию.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню