2010-09-01 12 views
11

Ich habe ein WPF-DataGrid mit einem AlternatingRowBackground-Pinsel. Es ist so konfiguriert, dass es jede zweite Zeile einfärbt. Ich möchte etwas mit der Maus machen, um die aktuelle Zeile zu markieren. Allerdings scheint der Style-Trigger gegenüber dem AlternatingRowBackground-Pinsel zu verlieren. Ich bekomme die gewünschte Zeilenfarbe auf der Maus über ... aber nur auf den Zeilen, die nicht mit dem AlternatingRowBackground-Pinsel gemalt sind. HierWPF-Style-Trigger für DataGridRow-Hintergrundfarbe von AlternatingRowBackground-Pinsel übertrumpft

ist der Stil in Windows.Resources:

<Window.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="/Skins/MainSkin.xaml" /> 
      </ResourceDictionary.MergedDictionaries> 
      <Style TargetType="{x:Type DataGridRow}"> 
       <Style.Triggers> 
        <Trigger Property="IsMouseOver" 
          Value="True"> 
         <Setter Property="Background" 
           Value="Red" /> 
         <Setter Property="FontWeight" 
           Value="ExtraBold" /> 
         <Setter Property="Height" 
           Value="20" /> 
        </Trigger> 
       </Style.Triggers> 
      </Style> 
     </ResourceDictionary> 
    </Window.Resources> 

Und hier ist das Datagrid:

<DataGrid Margin="25,15,25,0" 
       VerticalAlignment="Top" 
       ItemsSource="{Binding DocumentTypeList}" 
       AutoGenerateColumns="False" 
       Height="500" 
       AlternationCount="2" 
       FrozenColumnCount="2" 
       AlternatingRowBackground="{DynamicResource AlternatingRow}"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding Abbreviation}" 
           Header="Abbreviation" /> 
      <DataGridTextColumn Binding="{Binding Title}" 
           Header="Title" /> 

      <DataGridTextColumn Binding="{Binding Fee}" 
           Header="Fee" /> 
      <DataGridTextColumn Binding="{Binding SpecialInstructions}" 
           Header="Special Instructions" /> 
     </DataGrid.Columns> 
    </DataGrid> 

Gibt es eine Möglichkeit, den absoluten Sieger zu erklären? Liegt das Problem an einer Hierarchie? Es scheint mir, dass der AlternatingRowBackground-Pinsel gewinnt, weil er direkt mit dem spezifischsten Teil der Deklaration verknüpft ist.

Update: Hier ist die korrekte Syntax, basierend auf @ Val Führung:

<Window.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <ResourceDictionary Source="/Skins/MainSkin.xaml" /> 
     </ResourceDictionary.MergedDictionaries> 
     <Style TargetType="{x:Type DataGridRow}"> 
      <Style.Triggers> 
       <Trigger Property="IsMouseOver" 
         Value="True"> 
        <Setter Property="Background" 
          Value="Red" /> 
        <Setter Property="FontWeight" 
          Value="ExtraBold" /> 
        <Setter Property="Height" 
          Value="20" /> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
     <Style TargetType="{x:Type DataGrid}"> 
      <Setter Property="AlternatingRowBackground" Value="{DynamicResource AlternatingRow}"/> 
     </Style> 
    </ResourceDictionary> 
</Window.Resources> 

Und das Datagrid (minus der AlternatingRowBackground Bürste):

<DataGrid Margin="25,15,25,0" 
       VerticalAlignment="Top" 
       ItemsSource="{Binding DocumentTypeList}" 
       AutoGenerateColumns="False" 
       Height="500" 
       AlternationCount="2" 
       FrozenColumnCount="2"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding Abbreviation}" 
           Header="Abbreviation" /> 
      <DataGridTextColumn Binding="{Binding Title}" 
           Header="Title" /> 

      <DataGridTextColumn Binding="{Binding Fee}" 
           Header="Fee" /> 
      <DataGridTextColumn Binding="{Binding SpecialInstructions}" 
           Header="Special Instructions" /> 
     </DataGrid.Columns> 
    </DataGrid> 

Antwort

5

Was in der für mich gearbeitet hat Vergangenheit mit dieser Art von Sache, ist es, einen Setter außerhalb der Auslöser zu verwenden zB:

<Style TargetType="{x:Type DataGridRow}"> 
    <Style.Triggers> 
     <Trigger Property="IsMouseOver" 
       Value="True"> 
      <Setter Property="Background" 
        Value="Red" /> 
      <Setter Property="FontWeight" 
        Value="ExtraBold" /> 
      <Setter Property="Height" 
        Value="20" /> 
     </Trigger> 
    </Style.Triggers> 
    <Setter Property="AlternatingRowBackground" 
      Value="{DynamicResource AlternatingRow}"/> 
</Style> 

Und sie entfernen die Eigenschaft verbindlich auf der DataGrid selbst. Obwohl ich dies normalerweise mit Datenauslösern und nicht normalerweise mit dynamischen Ressourcenbindungen mache. Aber immer noch einen Schuss wert

+0

Sie auf jeden Fall mich in die richtige Richtung gehen. Ich habe die Setter-Eigenschaft wie von Ihnen vorgeschlagen hinzugefügt ... nicht zu {x: Type DataGridRow}, sondern als separaten Stil für {x: Type DataGrid}. Das macht den Trick. –

+0

Danke! Nicht sicher, warum das Definieren des AlternatingRowBackground in einem DataGrid-Stil statt in DataGrid.AlternatingRowBackground den Trigger direkt ermöglicht, aber ich bin froh, dass es funktioniert! –

18

Es gibt zwei Möglichkeiten, dies zu tun, keiner ist besonders offensichtlich. Da DataGridRow (in Code) die Hintergrundeigenschaft vom übergeordneten DataGrid in einen lokalen Wert in der Zeile überträgt, hat sie Vorrang vor dem Wert, der von Ihrem Trigger festgelegt wurde.

Der erste (und einfachste) Weg besteht darin, nicht AlternatingRowBackground oder RowBackground zu verwenden, sondern stattdessen Trigger zu verwenden, um die Hintergrundfarbe wie von Val vorgeschlagen zu wechseln. Sein Beispiel ist jedoch nicht vollständig und funktioniert nicht wie es ist. Der korrekte Stil und die korrekte Verwendung wären wie folgt. Beachten Sie, dass Sie AlternationCount für DataGrid festlegen müssen, da andernfalls die Zeilen keine alternierenden Indizes erhalten.

<DataGrid AlternationCount="2"> 
    <DataGrid.RowStyle> 
     <Style TargetType="DataGridRow"> 
      <Setter Property="Background" Value="White"/> 
      <Setter Property="FontWeight" Value="Normal"/> 
      <Style.Triggers> 
       <Trigger Property="AlternationIndex" Value="1"> 
        <Setter Property="Background" Value="Wheat"/> 
        <Setter Property="FontWeight" Value="Bold"/> 
       </Trigger> 
       <Trigger Property="IsMouseOver" Value="True"> 
        <Setter Property="Background" Value="Khaki"/> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </DataGrid.RowStyle> 
</DataGrid> 

Die zweite Option ist die Verwendung des VisualStateManager. Dies gibt Ihnen viel mehr Kontrolle über die verschiedenen visuellen Zustände, aber es ist ausführlicher. Glücklicherweise ist es ziemlich einfach, die Standardsteuervorlage mit Blend zu kopieren. Die meisten der folgenden Elemente sind bis auf das Storyboard im MouseOver-Status unverändert und ich habe einen Hintergrund für das selectiveScrollingGrid festgelegt.

Sorry für den Wrap, aber wie ich schon sagte, es ist ein bisschen mehr wortreich.

<DataGrid AlternationCount="2" AlternatingRowBackground="Wheat"> 
    <DataGrid.RowStyle> 
    <Style TargetType="DataGridRow"> 
     <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="DataGridRow"> 
      <Border x:Name="DGR_Border" 
        Background="{TemplateBinding Background}" 
        BorderBrush="{TemplateBinding BorderBrush}" 
        BorderThickness="{TemplateBinding BorderThickness}" 
        SnapsToDevicePixels="True"> 
       <VisualStateManager.VisualStateGroups> 
       <VisualStateGroup x:Name="CommonStates"> 
        <VisualState x:Name="Normal"/> 
        <VisualState x:Name="Normal_AlternatingRow"/> 
        <VisualState x:Name="Unfocused_Editing"/> 
        <VisualState x:Name="Normal_Editing"/> 
        <VisualState x:Name="Unfocused_Selected"/> 
        <VisualState x:Name="Normal_Selected"/> 
        <VisualState x:Name="MouseOver_Unfocused_Editing"/> 
        <VisualState x:Name="MouseOver_Editing"/> 
        <VisualState x:Name="MouseOver_Unfocused_Selected"/> 
        <VisualState x:Name="MouseOver_Selected"/> 
        <VisualState x:Name="MouseOver"> 
        <Storyboard Storyboard.TargetName="Highlight"> 
         <ColorAnimation Duration="0" Storyboard.TargetProperty="Color" To="Khaki"/> 
        </Storyboard> 
        </VisualState> 
       </VisualStateGroup> 
       </VisualStateManager.VisualStateGroups> 
       <SelectiveScrollingGrid x:Name="selectiveScrollingGrid"> 
       <SelectiveScrollingGrid.Background> 
        <SolidColorBrush x:Name="Highlight" Color="Transparent"/> 
       </SelectiveScrollingGrid.Background> 
       <SelectiveScrollingGrid.ColumnDefinitions> 
        <ColumnDefinition Width="Auto"/> 
        <ColumnDefinition Width="*"/> 
       </SelectiveScrollingGrid.ColumnDefinitions> 
       <SelectiveScrollingGrid.RowDefinitions> 
        <RowDefinition Height="*"/> 
        <RowDefinition Height="Auto"/> 
       </SelectiveScrollingGrid.RowDefinitions> 
       <DataGridCellsPresenter Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
       <DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Visibility="{TemplateBinding DetailsVisibility}"/> 
       <DataGridRowHeader Grid.RowSpan="2" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/> 
       </SelectiveScrollingGrid> 
      </Border> 
      </ControlTemplate> 
     </Setter.Value> 
     </Setter> 
    </Style> 
    </DataGrid.RowStyle> 
</DataGrid> 
+0

Danke Josh.Ich mag die erste Option, die Sie beschreiben. Ich wünschte, ich könnte die akzeptierte Antwort teilen. –

+0

LOL spielt eigentlich keine Rolle, sollte aber nicht die akzeptierte Antwort zumindest kompilieren? :) – Josh

+1

Ha ha! Wahrscheinlich so ... aber ich würde mich grausam fühlen, wenn ich eine Antwort von jemandem mit 16 Reputation gegen deine 17.3k wegnehmen würde ... :) –

Verwandte Themen