WpfToolkit DataGrid: выделение измененных строк - PullRequest
2 голосов
/ 09 февраля 2011

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

Ответы [ 3 ]

4 голосов
/ 09 февраля 2011
<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 создает виртуальную машину для каждого элемента в большинстве случаев.

2 голосов
/ 30 июня 2012

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

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

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

1 голос
/ 09 февраля 2011

INotifyPropertyChanged - не единственный интерфейс, который привязка WPF может использовать для уведомлений об изменениях, это просто тот, к которому мы больше всего привыкли. Как Bea Stollnitz пишет , 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 объекты.

...