2010-01-29 3 views
5

У меня вопрос о привязке данных DataGrid в WPF. Я использую VS 2010 Beta 2, у которого есть собственный DataGrid, а не Toolkit, хотя я думаю, что это почти то же самое.Динамическое связывание в шаблоне DataGridCell WPF

Я хочу привязать к набору данных, который содержит 52 столбца, по одному на каждую неделю года. По этой причине я хочу связать данные динамически, а не указывать каждое поле. Значение для каждого поля является истинным или ложным в зависимости от некоторого условия. Основываясь на этом значении, я хочу показать изображение в шаблоне ячейки, если условие истинно и скрыть его, если условие неверно.

Моя проблема в том, что все примеры использования шаблонов, которые я нашел, относятся к случаю фиксированных предопределенных полей, где вы можете иметь привязку, такую ​​как Text = "{Binding UserName}". Это не хорошо для меня, потому что я не знаю, что имена полей будут во время разработки.

Я составил упрощенный пример, который иллюстрирует проблему. В этом примере создается таблица данных, которая содержит истинные и ложные значения. Изображение в моем шаблоне никогда не отображается. Как я могу сделать его невидимым в зависимости от истинного или ложного значения в данных?

<Window.Resources> 

    <!--This is the bit that doesn't work...--> 
    <Style TargetType="{x:Type Image}" x:Key="HideWhenFalse"> 
     <Setter Property="Visibility" Value="Hidden" /> 
     <Style.Triggers> 
      <DataTrigger 
     Binding="{Binding Path=???}" 
     Value="True"> <!--What to put for the path? --> 
       <Setter Property="Visibility"> 
        <Setter.Value> 
         Visible 
        </Setter.Value> 
       </Setter> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
    <!--Up to here--> 

    <Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <StackPanel> 
         <Image Source="Images/tick.bmp" Style="{StaticResource HideWhenFalse}"> 

         </Image> 
        </StackPanel> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Window.Resources> 

<Grid> 
    <DataGrid 
     x:Name="myDataGrid" 
     AutoGenerateColumns="True" > 

    </DataGrid> 
</Grid> 

Код позади:

общественный частичный класс MainWindow: Window {

public MainWindow() 
{ 
    InitializeComponent(); 

    DataTable dtTable = new DataTable(); 

    dtTable.Columns.Add("A", typeof(Boolean)); 
    dtTable.Columns.Add("B", typeof(Boolean)); 
    dtTable.Columns.Add("C", typeof(Boolean)); 
    dtTable.Columns.Add("D", typeof(Boolean)); 
    dtTable.Columns.Add("E", typeof(Boolean)); 
    dtTable.Columns.Add("F", typeof(Boolean)); 

    for (int i = 0; i < 5; i++) 
    { 
     object[] oValues = new Object[dtTable.Columns.Count]; 

     for (int j = 0; j < dtTable.Columns.Count; j++) 
     { 
      oValues[j] = (j % 2 == 1) ? true : false; 
     } 

     dtTable.Rows.Add(oValues); 
    } 

    myDataGrid.ItemsSource = dtTable.DefaultView; 
    myDataGrid.Items.Refresh(); 
} 

}

NB Это, вероятно, очевидно, и я приближаюсь к проблеме совершенно неправильно. Вот исповедь: я уже пару месяцев пытаюсь разглядеть WPF, и мне все еще кажется, что я приближаюсь к КАЖДОЙ проблеме неправильно. Надеюсь, скоро пенни упадут.

ответ

9

Вы можете использовать MultiBinding с первым связыванием, принимающим фактический контекст данных из ячейки (это будет строка), а второй - с столбцом. Оттуда вы можете получить значение ячейки.

код Преобразователь:

public class RowColumnToCellConverter : IMultiValueConverter { 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { 
     DataRowView row = values[0] as DataRowView; 
     DataGridColumn column = values[1] as DataGridColumn; 
     return row != null && column != null 
      ? row[column.SortMemberPath] 
      : DependencyProperty.UnsetValue; 
    } 

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

XAML:

<Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <StackPanel> 
         <TextBlock x:Name="TextOK" Text="OK" Visibility="Collapsed" /> 
        </StackPanel> 
        <ControlTemplate.Triggers> 
         <DataTrigger Value="True"> 
          <DataTrigger.Binding> 
           <MultiBinding Converter="{StaticResource RowColumnToCellConverter}"> 
            <Binding /> 
            <Binding RelativeSource="{x:Static RelativeSource.Self}" Path="Column" /> 
           </MultiBinding> 
          </DataTrigger.Binding> 
          <Setter TargetName="TextOK" Property="Visibility" Value="Visible" /> 
         </DataTrigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

Я использовал TextBlock вместо изображения для тестирования, но код будет таким же. Просто избегайте определения стиля для изображения, если это можно сделать непосредственно в стиле DataGridCell.

+0

Спасибо за ваш очень быстрый ответ, Жюльен. Это работает. – Richard

+1

@ Рихард - вы должны принять этот ответ – David

+0

merci bien, ça m'a beaucoup aidé! – David

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