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.
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)
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.”
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
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)
Bitte keine Full Quotes
[Hinweis] Wie poste ich richtig?
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.”
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?
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.”
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ß