Laden...

WPF Datagrid Zellen nach Inhalt von einem Excel Dokument färben.

Erstellt von bmw2001 vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.406 Views
B
bmw2001 Themenstarter:in
5 Beiträge seit 2019
vor 4 Jahren
WPF Datagrid Zellen nach Inhalt von einem Excel Dokument färben.

Hallo Forum,

Ich bin relativ neu in WPF und MVVM und stehe ein wenig vor einem Problem.
Das Wochenende habe ich probiert meine Zellen des Datagrids abhängig von meinem Inhalt und auch der Farbe zu ändern, jedoch weiss ich nicht genau wie ich das mit dem Binding mache. Mein XAML sieht bisher so aus:

<Window.Resources>
        <local:NameToBrushConverter x:Key="NameToBrushConverter"/>
        <Style x:Key="CellStyle" TargetType="DataGridCell">
            <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource NameToBrushConverter}}" />
        </Style>
    </Window.Resources>

<DataGrid x:Name ="TableView" ItemsSource="{Binding Workerlist}" Grid.Column="1" Grid.Row="4" IsReadOnly="True" CellStyle="{StaticResource CellStyle}"/>

Das ist mein Converter:

public class NameToBrushConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string input = value as string;
            switch (input)
            {
                case "Urlaub":
                    return "Blue"; ;
                default:
                    return "Green"; ;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

input ist immer null, daher weiss ich nicht genau was ich vom Binding anders machen muss damit es den Inhalt aus der Zelle bekommt. Außerdem habe ich immer gesehen, dass viele das machen:

return Brushes.LightGreen;

Dabei würde sich aber die Zellfarbe bei mir gar nicht ändern.

Hinzu kommt noch die Frage, wie ich meinem Converter die Farben zum jeweiligen Inhalt am Besten mitgebe, da ich aktuell zum Testen es anhand von Urlaub nur statisch gemacht habe.

Das Excel Dokument auslesen tue ich auch mit zwei for schleifen:

tmp = new worker();
tmp.Name = xlRange.Cells[i, j].Value2;
tmp.Color = xlRange.Cells[i, j].Interior.Color.ToString();
workers.Add(tmp);

Gibt es irgendeine Möglichkeit diese Worker Liste an die Converter Klasse zu übergeben, da sobald mein Datagrid gefüllt ist, die Liste ja nicht mehr vorhanden ist und der Converter ja erst später aufgerufen wird.

132 Beiträge seit 2013
vor 4 Jahren

Ich bin etwas verwirrt. Dein "NameToBrushConverter" sollte doch einen Brush zurückgeben? Du gibst strings zurück.

return Brushes.LightGreen;

wäre da in der Tat richtig(er)

U
69 Beiträge seit 2019
vor 4 Jahren

Da gebe ich ByteDevil recht...
Was mir auch noch auffällt:

Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource NameToBrushConverter}}"

Du übergibst dem Converter eine DataGridCell. Das heisst, dass dein Cast

string input = value as string;

immer null zurück gibt.
Du müsstest dem Binding dann noch soetwas hinzufügen (Vorrausgesetzt du hast das ContentTemplate nicht angepasst):

,Path=Content.Text

Ggf. mal mit dem Debugger schauen was als value tatsächlich dem Converter übergeben wird.

“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”

  • Patrick to Spongebob
S
248 Beiträge seit 2008
vor 4 Jahren

Wenn das Bindungsziel vom Typ Brush ist kann der Converter auch einen Namen (string) aus der statischen Brushes Klasse zurückgeben. Diese wird automatisch in den passenden Brush konvertiert so wie als wäre dieser im XAML direkt gestanden.

Grüße

B
bmw2001 Themenstarter:in
5 Beiträge seit 2019
vor 4 Jahren

Vielen Dank, der Path war immer falsch weil ich immer Content oder Text probiert habe, aber nie Content.Text bzw hab ihn ja am Ende ganz weggelassen!
Und das mit der Brush habe ich auch angepasst.

Nun nochmal zu meiner letzten Frage, wie bekomme ich die Farben die ich in meinem ViewModel auslese in diesen Converter, da ja der Converter erst aufgerufen wird nachdem das ViewModel durch ist und die Daten nicht mehr vorhanden sind. (Ist auch generell gemeint für Daten die ich vlt später irgendwo anders brauche könnte)

Hinweis von Abt vor 4 Jahren

Bitte keine Full Quotes
[Hinweis] Wie poste ich richtig?

U
69 Beiträge seit 2019
vor 4 Jahren

Du gibst bei deinem DataGrid ja schon die Workerlist als ItemsSource mit.
D.h. jede Zeile aus deinem DataGrid ist an ein Worker-Item aus deiner Workerlist gebunden.
Du kannst dann dem Converter als ConverterParameter die Color vom Worker mitgeben.
In etwa so:

 <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource NameToBrushConverter}, ConverterParameter={Binding Color}}" />

und dann könntest du wahrscheinlich im selben Zug die RelativeSource entfernen und hier auch mit dem Binding arbeiten.

 <Setter Property="Background" Value="{Binding Name, Converter={StaticResource NameToBrushConverter}, ConverterParameter={Binding Color}}" />

Dann sparst du dir auch das Path=Content.Text.

Dann stellt sich mir die Frage ob du im Coverter überhaupt noch den Worker.Name brauchst. Wenn nicht, kannst du dann auch direkt an die Color binden...

“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”

  • Patrick to Spongebob
B
bmw2001 Themenstarter:in
5 Beiträge seit 2019
vor 4 Jahren

Sobald ich ein Binding für den ConvertParameter festlegen will, erhalte ich:

Fehlermeldung:
A 'Binding' cannot be set on the 'ConverterParameter' property of type 'Binding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject

Muss ich erst ein Property in meinem ViewModel anlegen oder was für eine Möglichkeit habe ich?

U
69 Beiträge seit 2019
vor 4 Jahren

Oh, ja, da war ich wohl etwas vorschnell.
Ein Binding auf den ConverterParameter ist tatsächlich nicht möglich 😦
Dann würde ich mir mal das Konzept der MultiValueConverter anschauen!

“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”

  • Patrick to Spongebob
S
9 Beiträge seit 2019
vor 4 Jahren

das geht über einen converter ganz einfach. hier mal ein snippet wie ich es geloöst habe.

der converter selber ist eine helperclass die ich als ressource eingebunden habe.

<DataGridTextColumn Header="Winrate" Binding="{Binding winrate}" HeaderStyle="{StaticResource ShipDataGridHeader}" CellStyle="{StaticResource ShipDataGridCells}" Width="90">
                            <DataGridTextColumn.ElementStyle>
                                <Style TargetType="TextBlock">
                                    <Setter Property="Foreground" Value="{Binding winrate, Converter={StaticResource CellConverter}}"/>
                                </Style>
                            </DataGridTextColumn.ElementStyle>
                        </DataGridTextColumn>

hier färbe ich die textfarbe ein. je nach wert. das geht aber auch mit den hintergrund der zellen genauso. du musst nur genau angeben was du verändern willst.


<Setter Property="Foreground" Value="{Binding winrate, Converter={StaticResource CellConverter}}"/>

diese zeile ändert die schriftfarbe. in "Value" bekomme ich über das binding einen wert den ich an den converter übergebe. dieser converter liefert mir die dem wert zugeordnete farbe als string im format "#FFXXXXXX" zurück.
gruß