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

Есть ли способ выделить все измененные строки в 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>

person Phil Gan    schedule 09.02.2011    source источник


Ответы (3)


<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. Таким образом, прямая привязка к этому свойству не даст надежных результатов.
Кажется, что вам нужно оборачивать элементы данных. Я рекомендую сделать ViewModel для элементов и добавить свойство, которое говорит, изменилась ли строка с уведомлением об изменении (INotifyPropertyChanged или DP) и привязать к этому свойству. Конечно, будут и другие альтернативы, но IMO создание виртуальной машины для каждого элемента в большинстве случаев является лучшим решением.

person HCL    schedule 09.02.2011
comment
Это работает для вас? Я не вижу, чем он отличается от моего. Я обновил вопрос, кстати. - person Phil Gan; 09.02.2011

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

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

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

person William    schedule 29.06.2012

INotifyPropertyChanged — не единственный интерфейс, который привязка WPF может использовать для уведомлений об изменениях, это просто тот, к которому мы больше всего привыкли. Как пишет Беа Столлниц, ADO DataView реализует IBindingList, который реализует уведомление об изменении, вызывая ListChanged при изменении списка или элемента в нем.

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

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

Изменить

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

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

person Robert Rossney    schedule 09.02.2011