2010-01-29 17 views
5

Ich habe eine Frage zur Datenbindung DataGrid in WPF. Ich verwende die VS 2010 Beta 2, die ihr eigenes DataGrid hat, nicht das Toolkit, obwohl ich denke, dass es ziemlich dasselbe ist.Dynamische Bindung in WPF DataGridCell Vorlage

Ich möchte an eine Datenmenge binden, die 52 Spalten hat, eine für jede Woche des Jahres. Aus diesem Grund möchte ich die Daten dynamisch binden, anstatt jedes Feld anzugeben. Der Wert für jedes Feld ist abhängig von einer Bedingung wahr oder falsch. Basierend auf diesem Wert möchte ich ein Bild in der Zellenvorlage anzeigen, wenn die Bedingung wahr ist, und es ausblenden, wenn die Bedingung nicht erfüllt ist.

Mein Problem ist, dass alle Beispiele der Verwendung von Vorlagen, die ich gefunden habe, beziehen sich auf den Fall von festen, vordefinierten Feldern, wo Sie eine Bindung wie Text = "{Binding UserName}" haben können. Das ist nicht gut für mich, weil ich nicht weiß, was die Feldnamen zur Entwurfszeit sein werden.

Ich habe ein vereinfachtes Beispiel erstellt, das das Problem veranschaulicht. In diesem Beispiel wird eine Datentabelle generiert, die wahre und falsche Werte enthält. Das Bild in meiner Vorlage ist niemals sichtbar. Wie würde ich es unsichtbar machen, abhängig vom wahren oder falschen Wert in den Daten?

<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> 

-Code hinter:

public partial class Mainwindow: Fenster {

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 Das ist wahrscheinlich offensichtlich und ich nähere mich dem Problem auf völlig falsche Weise. Hier ist ein Geständnis: Ich habe seit ein paar Monaten versucht, mich mit WPF zu beschäftigen, und ich scheint mich immer noch auf JEDES Problem in der falschen Richtung zu stoßen. Ich hoffe, der Pfennig fällt bald.

Antwort

9

Sie können eine MultiBinding verwenden, mit einer ersten Bindung, die den tatsächlichen Datenkontext von der Zelle nimmt (das wäre die Zeile), und der zweite die Spalte. Von dort können Sie den Zellenwert abrufen.

Converter Code:

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> 

Ich benutzen ein TextBlock stattdessen ein Bild für die Prüfung, aber der Code wird das gleiche sein. Vermeiden Sie es, einen Stil für das Bild zu definieren, wenn dies direkt im Format DataGridCell möglich ist.

+0

Danke für Ihre sehr schnelle Antwort, Julien. Es funktioniert ein Vergnügen. – Richard

+1

@Richard - Sie sollten diese Antwort akzeptieren – David

+0

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