2017-04-10 1 views
1

J'ai une grille de données qui est une calculatrice financière avec des cellules qui deviennent rouges sur les valeurs négatives. Ceci est fait via DataTrigger avec convertisseur. J'ai également surpassé la couleur de sélection du surlignage du système. Mon problème maintenant est que lorsque je sélectionne une rangée, les cellules rouges ne sont pas mises en surbrillance.Grille de données WPF. Impossible de mettre en évidence une cellule personnalisée

Here's the picture

Pour autant que je comprends le style de cellule personnalisée sélection emporte. Je veux que ma cellule rouge personnalisée soit également mise en évidence avec une barre bleue de 0,5 opacité. Comment puis-je réparer cela? Eh bien, je peux ajouter un déclencheur supplémentaire au style de cellule qui change la couleur BG lors de la sélection et ajuster la couleur pour s'adapter, mais c'est plutôt un kludge. Ou peut-être que je peux implémenter une couleur de superposition avec l'opacité ici d'une façon ou d'une autre?

<Trigger Property="IsSelected" Value="True"> 
    <Setter Property="Background" Value="LightBlue" /> 
</Trigger> 

Ci-dessous le code complet. C'est un exemple dépouillé, léger mais qui fonctionne pleinement.

XAML

<Window.Resources> 
     <local:ValueToBoolConverter x:Key="ValueToBoolConverter"/> 
    </Window.Resources> 
    <Grid> 
     <DataGrid ItemsSource="{Binding MainTable}" 
        AutoGenerateColumns="False" 
        CanUserAddRows="False"> 
      <DataGrid.RowStyle> 
       <Style TargetType="DataGridRow"> 
        <Setter Property="Background" Value="Azure"/> 
        <Style.Resources> 
         <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Blue" Opacity="0.5" /> 
         <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" /> 
         <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Transparent" /> 
        </Style.Resources> 
       </Style> 
      </DataGrid.RowStyle> 
      <DataGrid.Columns> 
       <DataGridTextColumn Header="Income Day" Binding="{Binding IncomeDay}" /> 
       <DataGridTextColumn Header="Income Week" Binding="{Binding IncomeWeek}"> 
        <DataGridTextColumn.CellStyle> 
         <Style TargetType="DataGridCell"> 
          <Style.Triggers> 
           <DataTrigger Binding="{Binding IncomeWeek, Converter={StaticResource ValueToBoolConverter}}" Value="true"> 
            <Setter Property="Background" Value="Salmon"/> 
           </DataTrigger> 
          </Style.Triggers> 
         </Style> 
        </DataGridTextColumn.CellStyle> 
       </DataGridTextColumn> 
       <DataGridTextColumn Header="Income Month" Binding="{Binding IncomeMonth}" /> 
       <DataGridTextColumn Header="Income Year" Binding="{Binding IncomeYear}" Width="*" /> 
      </DataGrid.Columns> 
     </DataGrid> 
    </Grid> 

C#

using System; 
using System.Collections.ObjectModel; 
using System.Globalization; 
using System.Windows; 
using System.Windows.Data; 

namespace Datagrid_Cell_Highlight 
{ 
    public class TableData 
    { 
     public decimal IncomeDay { get; set; } 
     public decimal IncomeWeek { get; set; } 
     public decimal IncomeMonth { get; set; } 
     public decimal IncomeYear { get; set; } 
    } 

    public class ViewModel 
    { 
     public ObservableCollection<TableData> MainTable { get; set; } 
     public ViewModel() 
     { 
      MainTable = new ObservableCollection<TableData> 
      { 
       new TableData { IncomeDay = (decimal)1.11 }, 
       new TableData { IncomeDay = (decimal)2.22 }, 
       new TableData { IncomeDay = (decimal)-1.23 }, 
       new TableData { IncomeDay = (decimal)-2.34 } 
      }; 
      foreach (var table in MainTable) 
      { 
       table.IncomeWeek = table.IncomeDay * 7; 
       table.IncomeMonth = table.IncomeDay * 30; 
       table.IncomeYear = table.IncomeDay * 365; 
      } 
     } 
    } 

    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = new ViewModel(); 
     } 
    } 

    public class ValueToBoolConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      if ((value is decimal) && ((decimal)value < 0)) 
       return true; 
      else return false; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

Répondre

0

« bidouille » ou non, la Background de la cellule en effet « remplacer » l'arrière-plan de la ligne vous devez donc ajouter un autre déclencheur à la cellule style qui prend cela en considération. Vous pouvez par exemple utiliser un MultiDataTrigger et un DrawingBrush qui contient à la fois rouge et une brosse bleue:

<DataGridTextColumn Header="Income Week" Binding="{Binding IncomeWeek}"> 
    <DataGridTextColumn.CellStyle> 
     <Style TargetType="DataGridCell"> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding IncomeWeek, Converter={StaticResource ValueToBoolConverter}}" Value="true"> 
        <Setter Property="Background" Value="Salmon"/> 
       </DataTrigger> 
       <MultiDataTrigger> 
        <MultiDataTrigger.Conditions> 
         <Condition Binding="{Binding IncomeWeek, Converter={StaticResource ValueToBoolConverter}}" Value="true" /> 
         <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="True" /> 
        </MultiDataTrigger.Conditions> 
        <Setter Property="Background"> 
         <Setter.Value> 
          <DrawingBrush Viewport="0,0,1,1" TileMode="Tile"> 
           <DrawingBrush.Drawing> 
            <DrawingGroup> 
             <GeometryDrawing> 
              <GeometryDrawing.Geometry> 
               <RectangleGeometry Rect="0,0,1,1" /> 
              </GeometryDrawing.Geometry> 
              <GeometryDrawing.Brush> 
               <SolidColorBrush Color="Salmon"/> 
              </GeometryDrawing.Brush> 
             </GeometryDrawing> 
             <GeometryDrawing> 
              <GeometryDrawing.Geometry> 
               <RectangleGeometry Rect="0,0,1,1" /> 
              </GeometryDrawing.Geometry> 
              <GeometryDrawing.Brush> 
               <SolidColorBrush Color="Blue" Opacity="0.2"/> 
              </GeometryDrawing.Brush> 
             </GeometryDrawing> 
            </DrawingGroup> 
           </DrawingBrush.Drawing> 
          </DrawingBrush> 
         </Setter.Value> 
        </Setter> 
       </MultiDataTrigger> 
      </Style.Triggers> 
     </Style> 
    </DataGridTextColumn.CellStyle> 
</DataGridTextColumn> 
+0

Est-ce exactement ce dont j'ai besoin. Accepté. – Disodium

0

Vous pouvez y parvenir en utilisant MultiDataTrigger. Mais pourquoi pensez-vous que c'est un "kludge"? Je pense que c'est plutôt élégant.

Une alternative au code de mm8 est de simplement définir deux MultiDataTrigger. Le premier à déclencher quand IsSelected est faux et le second quand IsSelected est vrai.

<DataGridTextColumn.CellStyle> 
    <Style TargetType="DataGridCell">    
     <Style.Triggers> 
      <MultiDataTrigger> 
       <MultiDataTrigger.Conditions> 
        <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="False"/> 
        <Condition Binding="{Binding IncomeWeek, Converter={StaticResource ValueToBoolConverter}}" Value="True"/> 
       </MultiDataTrigger.Conditions> 
       <MultiDataTrigger.Setters> 
        <Setter Property="Background" Value="Salmon"/> 
       </MultiDataTrigger.Setters> 
      </MultiDataTrigger> 
      <MultiDataTrigger> 
       <MultiDataTrigger.Conditions> 
        <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True"/> 
        <Condition Binding="{Binding IncomeWeek, Converter={StaticResource ValueToBoolConverter}}" Value="True"/> 
       </MultiDataTrigger.Conditions> 
       <MultiDataTrigger.Setters> 
        <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> 
        <Setter Property="BorderThickness" Value="0"/> 
       </MultiDataTrigger.Setters> 
      </MultiDataTrigger> 
     </Style.Triggers> 
    </Style> 
</DataGridTextColumn.CellStyle> 
+0

Cela fonctionne, upvoted, mais j'ai accepté la réponse de mm8 parce que son implémente l'opacité. En ce qui concerne «kludge», je ne vois pas de moyen simple de réutiliser cette approche pour plusieurs colonnes. Mais c'est peut-être une autre question. – Disodium