Laden...

Ampel in DataGrid zeichnen, abhängig von Zellinhalt

Erstellt von NoSonOfMine vor einem Jahr Letzter Beitrag vor einem Jahr 523 Views
N
NoSonOfMine Themenstarter:in
17 Beiträge seit 2022
vor einem Jahr
Ampel in DataGrid zeichnen, abhängig von Zellinhalt

Hallo Community,

habe wieder einmal ein Thema auf das ich keine Antwort finde.

Ich habe ein DataGrid und erzeuge dort in XAML selbst Spalten. In der Spalte "Qualität" können die Zahlen 0,1 uns 2 stehen. Abhängig vom Zellwert färbe ich den Zellhintergrund entsprechend ein.

Nun möchte ich nicht die Zahlen sehen, sondern die Zahlen durch einen roten Kreis in Form einer "Ampel" visualisieren. D.h. 0 = roter Kreis (Ellipse), 1 = gelber Kreis , 2 = grüner Kreis. Wie realisiere ich das in XAML?

Hier mein aktueller Code:



                            <DataGrid Name="Dtg_MitarbeiterEntwicklungsProjekte" MouseDoubleClick="Dtg_Vorschauen_DoubleClick" AutoGenerateColumns="True">
                                <DataGrid.Columns>
                                    <DataGridTextColumn Header="ID" Binding="{Binding ID}"/>
                                    <DataGridTextColumn Header="Qualität" Binding="{Binding ProQuali}">
                                        <DataGridTextColumn.ElementStyle>
                                            <Style TargetType="TextBlock">
                                                <Style.Triggers>
                                                    <DataTrigger Binding="{Binding ProQuali}" Value="0">
                                                        <Setter Property="Background" Value="#FF0000"/>
                                                    </DataTrigger>
                                                    <DataTrigger Binding="{Binding ProQuali}" Value="1">
                                                        <Setter Property="Background" Value="#FFFF00"/>
                                                    </DataTrigger>
                                                    <DataTrigger Binding="{Binding ProQuali}" Value="2">
                                                        <Setter Property="Background" Value="#00FF00"/>
                                                    </DataTrigger>
                                                </Style.Triggers>
                                            </Style>
                                        </DataGridTextColumn.ElementStyle>
                                    </DataGridTextColumn>
                                    <DataGridCheckBoxColumn Header="Überfällig" Binding="{Binding Ueberfaellig, Mode=OneWay}"/>
                                    <DataGridTextColumn Header="Vertriebler" Binding="{Binding Vertriebler}"/>
                                    <DataGridTextColumn Header="Kunde" Binding="{Binding Kunde}"/>
                                    <DataGridTextColumn Header="Projekt" Binding="{Binding Projekt}"/>
                                    <DataGridTextColumn Header="Fortschritt" Binding="{Binding Fortschritt}"/>

                                </DataGrid.Columns>
                            </DataGrid>

16.835 Beiträge seit 2008
vor einem Jahr

Wenn das immer die gleichen "Ampeln" sind; nimm doch einfach ein Image mit einem SVG.
Die Bindung für die Zahl kannst beibehalten und einfach ein "Wert to SVG Image Converter" binden.


<Image Source="{Binding Path=myValue, Converter={StaticResource MyValueToSvgImageConverter}}" />

Aber gibt hunderte Wege für sowas.

P
257 Beiträge seit 2010
vor einem Jahr

Hallo NoSonOfMine!

Entweder du setzt Abt's Lösungsvorschlag um oder was dem auch sehr ähnlich ist, du implementierst einen IntegerToBrush-Konverter und benutzt ein Elipsen-Geometry-Objekt, dessen Fill-Eigenschaft an diesen Konverter gebunden wird.

Ein Kreis den du an den Integer-Wert bindest:


<Ellipse Width="12" Height="12"  Fill="{Binding Path=myValue, Converter={StaticResource MyValueToBrushConverter}}"/>

Falls du unterschiedliche Geometry-Objekte anzeigen möchtest (0=Daumen hoch, 1=Daumen runter, 2=Achtungs-Zeichen) kannst du einen IntegerToGeometry-Objekt Converter benutzen.


#region IntegerToGeometry-Konverter
/// <summary>
/// Konvertiert einen IntegerWert in ein Geometry-Objekt, dass aus den Path Eigenschaften (Path0 ... 5) extrahiert wird.
/// </summary>
[ValueConversion(typeof(int), typeof(Geometry))]
public class IntegerToGeometryConverter : IValueConverter
{
    #region Path(e) die die Geometrie, adäquat dem Integer-Wert, zur Verfügung stellen
    /// <summary>
    /// Geometry die bei Wert 0 zurückgegeben wird.
    /// </summary>
    public System.Windows.Shapes.Path Path0 { get; set; }
    /// <summary>
    /// Geometry die bei Wert 1 zurückgegeben wird.
    /// </summary>
    public System.Windows.Shapes.Path Path1 { get; set; }
    /// <summary>
    /// Geometry die bei Wert 2 zurückgegeben wird.
    /// </summary>
    public System.Windows.Shapes.Path Path2 { get; set; }
    /// <summary>
    /// Geometry die bei Wert 3 zurückgegeben wird.
    /// </summary>
    public System.Windows.Shapes.Path Path3 { get; set; }
    
    #endregion

    #region Vorwärts-Konverter
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int Wert = -1;                                                      // Wert zu dem das Geometry-Objekt zugeordnet werden soll, initalisieren

        if (value != null)                                                  // Wurde überhaupt ein Wert übergeben?
        {
            if (value.GetType() == typeof(int)) Wert = (int)value;          // Integer-Wert als Integer direkt übergeben? -> Integer-Wert in der Variable Wert speichern

            if (value.GetType() == typeof(string))                          // Oder eienen String, der sich in einen Integer-Wert konvertieren lässt übergeben?
            {
                if (!int.TryParse((string)value, out Wert)) return null;    // Wenn sich der übergebene String nicht in einen Integer-Wert konvertieren lässt, Konvertierung abbrechen
            }                                                               // Ansonsten steht der Integer-Wert in der Variable Wert.

            switch (Wert)                                                   // Zuordnung des Integer-Wertes zu einem Path.
            {
                case 0: return Path0?.Data;
                case 1: return Path1?.Data;
                case 2: return Path2?.Data;
                case 3: return Path3?.Data;
                case 4: return Path4?.Data;
                case 5: return Path5?.Data;
                case 6: return Path6?.Data;
                case 7: return Path7?.Data;
                case 8: return Path8?.Data;
                case 9: return Path9?.Data;
                case 10: return Path10?.Data;
            }
        }
        return null;                                                    // Wenn sich der Integer-Wert nicht zuordnen läßt, Null zurückgeben
    }
    #endregion

    #region Rückwärts-Konverter

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Geometry Geometrie = null;                                              // Leeres Geometry-Objekt initalisieren

        if (value != null)                                                      // Wurde überhaupt ein Wert übergeben?
        {
            if (value.GetType() == typeof(System.Windows.Shapes.Path))          // Wurde ein Path übergeben?
                Geometrie = ((System.Windows.Shapes.Path)value).Data;           // Geometry-Objekt des Path'es der Geometrie-Variable zuordnen
            if (value.GetType() == typeof(Geometry))                            // Wurde ein Geometry-Objekt übergeben?
                Geometrie = (Geometry)value;                                    // Geometry-Objekt der Geometrie-Variable zuordnen
            if (value.GetType() == typeof(ComboBoxItem))                        // Wurde ein ComboBox-Item (das ein Path-Objekt enthält)  übergeben?
            {
                ComboBoxItem cbi = (ComboBoxItem)value;                         // ComboBox-Item "holen"
                if (cbi.Content is System.Windows.Shapes.Path path)              // Enthält das ComboBox-Item ein Path-Objekt?
                    Geometrie = path.Data;                                      // Geometry-Objekt des Path'es der Geometrie-Variable zuordnen
            }

            if (Geometrie != null)                                              // Konnte aus dem Übergabewert ein Geometry-Objekt extrahiert werden?
            {                                                                   // Zuordnung des Geometrie-Objektes zu einem Integer-Werte.
                if (Path0 != null && Path0.Data.Equals(Geometrie)) return 0;     // Geometry des 0-Path'es wurde übergeben. 0 zurückgeben.
                if (Path1 != null && Path1.Data.Equals(Geometrie)) return 1;     // Geometry des 1-Path'es wurde übergeben. 1 zurückgeben.
                if (Path2 != null && Path2.Data.Equals(Geometrie)) return 2;     // Geometry des 2-Path'es wurde übergeben. 2 zurückgeben.
                if (Path3 != null && Path3.Data.Equals(Geometrie)) return 3;     // Geometry des 3-Path'es wurde übergeben. 3 zurückgeben.
                if (Path4 != null && Path4.Data.Equals(Geometrie)) return 4;     // Geometry des 4-Path'es wurde übergeben. 4 zurückgeben.
                if (Path5 != null && Path5.Data.Equals(Geometrie)) return 5;     // Geometry des 5-Path'es wurde übergeben. 5 zurückgeben.
                if (Path6 != null && Path6.Data.Equals(Geometrie)) return 6;     // Geometry des 6-Path'es wurde übergeben. 6 zurückgeben.
                if (Path7 != null && Path7.Data.Equals(Geometrie)) return 7;     // Geometry des 7-Path'es wurde übergeben. 7 zurückgeben.
                if (Path8 != null && Path8.Data.Equals(Geometrie)) return 8;     // Geometry des 8-Path'es wurde übergeben. 8 zurückgeben.
                if (Path9 != null && Path9.Data.Equals(Geometrie)) return 9;     // Geometry des 9-Path'es wurde übergeben. 9 zurückgeben.
                if (Path10 != null && Path10.Data.Equals(Geometrie)) return 10;  // Geometry des 10-Path'es wurde übergeben. 10 zurückgeben.
            }
        }
        return -1;                                                              // Wenn sich das Geometry-Objekt nicht zuordnen läßt, -1 als Kennzeichen das eine Zuordnung des Üb

126 Beiträge seit 2023
vor einem Jahr

Hier ein weiterer von den >100 möglichen Wegen:

Mit der DataGridTemplateColumn kann man das wie folgt umsetzen:


<Window
  x:Class="WpfApp1.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:col="clr-namespace:System.Collections;assembly=System.Runtime"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:local="clr-namespace:WpfApp1"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  Title="MainWindow"
  Width="800"
  Height="450"
  mc:Ignorable="d">

  <Window.Resources>
    <col:ArrayList x:Key="projects">
      <local:Projekt ID="1" ProQuali="0" />
      <local:Projekt ID="2" ProQuali="1" />
      <local:Projekt ID="3" ProQuali="2" />
    </col:ArrayList>

  </Window.Resources>
  <Grid>
    <DataGrid
      AutoGenerateColumns="False"
      CanUserAddRows="False"
      ItemsSource="{StaticResource projects}">
      <DataGrid.Columns>
        <DataGridTextColumn
          Binding="{Binding ID}"
          Header="Id"
          IsReadOnly="True" />
        <DataGridTextColumn
          Binding="{Binding ProQuali}"
          Header="Qualität"
          IsReadOnly="False" />

        <!--#region Template Column-->

        <DataGridTemplateColumn Header="Qualität">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <Ellipse Width="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight}" Margin="2">
                <Ellipse.Style>
                  <Style TargetType="Ellipse">
                    <Setter Property="Fill" Value="Red" />
                    <Style.Triggers>
                      <DataTrigger Binding="{Binding ProQuali}" Value="1">
                        <Setter Property="Fill" Value="Yellow" />
                      </DataTrigger>
                      <DataTrigger Binding="{Binding ProQuali}" Value="2">
                        <Setter Property="Fill" Value="Green" />
                      </DataTrigger>
                    </Style.Triggers>
                  </Style>
                </Ellipse.Style>
              </Ellipse>
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        <!--#endregion-->

      </DataGrid.Columns>
    </DataGrid>
  </Grid>
</Window>


using System.Windows;

namespace WpfApp1;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

public class Projekt
{
    public int ID { get; set; }
    public int ProQuali { get; set; }
}

Hat die Blume einen Knick, war der Schmetterling zu dick.