2010-09-02 1 views
2

Использование WPF DataGrid. Мне нужно изменить различные отображаемые и связанные свойства DataGridCell - такие как Foreground, FontStyle, IsEnabled и т. Д. - на основе соответствующего значения свойство объекта ячейки.Привязка свойства объекта ячейки к DataGridCell в WPF DataGrid

Теперь это легко сделать в коде, например (с использованием Observable Коллекция ObservableDictionaries):

var b = new Binding("IsLocked") { Source = row[column], Converter = new BoolToFontStyleConverter() }; 
    cell.SetBinding(Control.FontStyleProperty, b); 

и работает отлично, однако я не могу видеть, как сделать это в XAML, так как я могу найти способ установить Путь к свойству объекта ячейки.

Один попытки XAML является:

<Setter Property="FontStyle"> 
    <Setter.Value> 
     <MultiBinding Converter="{StaticResource IsLockedToFontStyleConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"> 
       <Binding /> 
       <Binding RelativeSource="{x:Static RelativeSource.Self}"/> 
     </MultiBinding> 
    </Setter.Value> 
</Setter> 

но нет привязки к не IsLocked свойство

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
{ 
    var row = (RowViewModel) values[0]; 
    var cell = (DataGridCell) values[1]; 
    if (cell != null && row != null) 
    { 
     var column = DataGridMethods.GetColumn(cell); 
     return row[column].IsLocked ? "Italic" : "Normal"; 
    } 

    return DependencyProperty.UnsetValue; 
} 

Пожалуйста, обратите внимание, что предыдущая версия вернулась строку [Col] .IsLocked и установите FontStyle с помощью DataTrigger, но возвращенный объект не привязан к базе данных.

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

Наконец, DataTable слишком неэффективны для моих требований, но мне было бы интересно посмотреть, как это делается с DataTables в любом случае, если есть такое решение для них, это может быть полезно в других местах (хотя я предпочитаю использовать коллекции).

Несомненно, это распространенная проблема, и я хочу, чтобы WPO noobie пытался запустить все MVVM в моем проекте, но эта проблема удерживает меня за использование WPF DataGrid.

ответ

4

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

Поместите ссылку на объект ячейки в свойстве тега DataGridCell. Я делаю это с помощью комбинации XAML и коды связывания внутри преобразователя следующим образом:.

и

public class CellViewModelToTagConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     var row = values[0] as RowViewModel; 
     var cell = values[1] as DataGridCell; 
     if (row != null && cell != null) 
     { 
      var column = DataGridMethods.GetColumn(cell); 
      // hack within hack!!! (using tag way is itself a hack?) 
      var b = new Binding("Self") {Source = row[column]}; 
      cell.SetBinding(FrameworkElement.TagProperty, b); 
      //... 
      //return row[column]; 
      return DependencyProperty.UnsetValue; 
     } 
     return DependencyProperty.UnsetValue; 
    } 

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

Вы можете сказать, что я думаю об этом решении моих комментариев внутри конвертера (Мне пришлось добавить свойство Self к объекту Cell и сделать Self = this в конструкторе).

По-прежнему он позволяет моей кодировке Datagrid быть полностью MVVM - если вы согласны с тем, что то, что я сделал внутри конвертера, согласуется с MVVM. Так или иначе, это работает!

Таким образом, я могу видеть и управлять всем, что есть в XAML, например, управлять этим связыванием только на определенных столбцах, помещая XAML в соответствующие ячейки cellstyles (что не делает это с помощью DataGrid.CellStyle).

Во всяком случае, пример использования является

<Style.Triggers> 
     <DataTrigger Value="true" Binding="{Binding RelativeSource={RelativeSource Self}, Path=Tag.IsLocked}"> 
      <Setter Property="FontStyle" Value="Italic"/> 
      <Setter Property="IsEnabled" Value="False"/> 
     </DataTrigger> 
</Style.Triggers> 

На уровне XAML он является простым и элегантным IMHO (особенно для различных ToolTips и Popups, для которых я делаю Интенсивное использование свойств объекта клетки). Однако я уверен, что есть лучший способ сделать это, не так ли?

Надеюсь, это все исчезнет, ​​когда я смогу использовать Net 4.0 и динамические объекты, но для этого проекта я не могу.

+0

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

+0

Я понимаю, что это старое сообщение, но я обнаружил, что могу просто поставить 'return row [column];' в блоке if .. и он работает. Каков код выше, выполняемый по-другому (т. Е. Создание привязки)? –

+0

Связывание не происходит, кроме IN преобразователя. Если вы не привязываетесь в конвертере и просто возвращаете строку [column], а затем обновляете указанную ячейку, она не привязана и вы не видите обновления в DataGrid. У меня есть намного лучшее и не-хакерское решение, хотя XAML сложнее. Я добавлю его здесь, когда у меня будет время. – Martino