Programmweit den Controls Farben per Listbox zuweisen

  • WPF

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

    Programmweit den Controls Farben per Listbox zuweisen

    Hallihallo,

    ich hab ne Frage:

    Ich möchte programmweit meinen Controls immer die gleiche Farbe mitgeben, und den User diese Farbe aus einer Listbox oder Combobox auswählen lassen.

    Ist es also möglich, den Inhalt einer List-/Combobox an die Farben anzubinden, die mir z. B. Intellisense vorschlägt. Und dann, wenn sich das ausgewählte Item ändert, die ausgewählte Farbe per DymamicResource den Controls zuzuweisen. Oder muss ich das aufwändig über Code Behind machen?

    Hab im Internet zwei komplette WPF Tutorials gefunden, aber zu diesem speziellen Fall finde ich nichts...

    EDIT: Hab mich ein bisschen durchgekämpft und hab es jetzt geschafft, dass mir eine Listbox alle verfügbaren Farben als Item anzeigt:

    XML-Quellcode

    1. <Window.Resources>
    2. <SolidColorBrush x:Key="Skin">
    3. </SolidColorBrush>
    4. </Window.Resources>
    5. <Grid x:Name="MeinGrid" Background="{DynamicResource Skin}">
    6. <ListBox Name="lstColors" Height="200" Width="200">
    7. <ListBox.ItemTemplate>
    8. <DataTemplate>
    9. <ListBoxItem Width="130" Content="{Binding ColorName}"/>
    10. </DataTemplate>
    11. </ListBox.ItemTemplate>
    12. </ListBox>
    13. </Grid>


    Wie mache ich es jetzt, dass in Zeile 3 als Wert das ausgewählte Item aus der Listbox (das den Farbname als String enthält) verwendet wird. Ich hätte da jetzt lstColors.SelectedItem reingeschrieben aber das funktioniert so natürlich nicht... Vielleicht irgendwie den String in eine Color umwandeln..?

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „kafffee“ ()

    Bin jetzt schon so weit:

    VB.NET-Quellcode

    1. Private Sub lstColors_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles lstColors.SelectionChanged
    2. Resources("Skin") = New SolidColorBrush(CType(lstColors.SelectedItem, Color))
    3. End Sub


    Aber da kommt der Fehler "Die angegebene Umwandlung ist ungültig".

    Hab auch schon das probiert:

    VB.NET-Quellcode

    1. Resources("Skin") = New SolidColorBrush(ColorConverter.ConvertFromString(lstColors.SelectedItem))


    Da kommt "Ungültige Konvertierung von Typ ColorInfo In Typ String"

    Dann hab ich da nochColor.FromName gefunden, aber das scheints nicht mehr zu geben... Nur:
    Color.FromArgb
    Color.FromAValues
    Color.FromRgb
    Color.FromScRgb
    Color.FromValues[/tt]

    Hat jemand noch eine Idee?

    Kann es sein, dass in lstColors.SelectedItem gar kein String drin ist, sondern ein Typ ColorInfo? Ich dachte bis jetzt dass Listboxen Strings enthalten und nicht auch andere Objekte...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „kafffee“ ()

    naja - mit dem Eventhandler haste dich scheints vom MVVM verabschiedet und bist aufs Niveau von WinForms zurückgegangen.

    Warum dann nicht bei WinForms bleiben?
    Da würde man das mit Databinding zwar auch eleganter abhandeln als mit sonem Eventhandlerr, aber zumindest würdest du dir kein falsches Wpf aneignen.
    @ErfinderDesRades

    Naja, bei Winforms hat man halt nicht die Möglichkeiten. Ausserdem wäre es gut mal was über Wpf zu lernen.

    Die Lösung erschien mir halt gut, weil sehr einfach und lesbar für mich.

    Ich hab mir deinen Link mal durchgelesen und bin nicht wirklich schlau draus geworden. Vermutlich fehlt mir der Gesamtüberblick, da sind schon von vornherein viele Wörter drin, die ich nicht versteh, fängt schon an bei ViewModel und MVVM...

    Hast du da vielleicht etwas was mehr meinem Kenntnisstand entspricht. Die Videos vom Sascha Patschka z. B. sind genau mein Tempo. Die ersten drei Videos hab ich schon gesehen und bin jetzt grad ein bisschen am Ausprobieren..
    Hi. Joshi an Joshi... lol ääh kafffee

    Ok Das was Du beschreibst geht in den Bereich "Themeing" und sollte wenn möglich in der "Application.xaml" stattfinden.

    XML-Quellcode

    1. <Application
    2. x:Class="Application"
    3. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    4. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    5. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    6. xmlns:local="clr-namespace:OkudaPlayer"
    7. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    8. StartupUri="Views\MainWindow.xaml"
    9. mc:Ignorable="d">
    10. <Application.Resources>
    11. <!-- LCARS Classic Theme -->
    12. <SolidColorBrush
    13. x:Key="Space-White-Brush"
    14. Color="#FFf5f6fa" />
    15. <SolidColorBrush
    16. x:Key="Violet-creme-Brush"
    17. Color="#FFddbbff" />
    18. <SolidColorBrush
    19. x:Key="Green-Brush"
    20. Color="#FF33cc99" />
    21. <SolidColorBrush
    22. x:Key="Magenta-Brush"
    23. Color="#FFcc4499" />
    24. <SolidColorBrush
    25. x:Key="Blue-Brush"
    26. Color="#FF4455ff" />
    27. <SolidColorBrush
    28. x:Key="Yellow-Brush"
    29. Color="#FFffcc33" />
    30. <SolidColorBrush
    31. x:Key="Violet-Brush"
    32. Color="#FF9944ff" />
    33. <SolidColorBrush
    34. x:Key="Orange-Brush"
    35. Color="#FFff7700" />
    36. <SolidColorBrush
    37. x:Key="African-Violet-Brush"
    38. Color="#FFcc88ff" />
    39. <SolidColorBrush
    40. x:Key="Text-Brush"
    41. Color="#FFcc77ff" />
    42. <SolidColorBrush
    43. x:Key="Red-Brush"
    44. Color="#FFdd4444" />
    45. <SolidColorBrush
    46. x:Key="Almond-Brush"
    47. Color="#FFffaa90" />
    48. <SolidColorBrush
    49. x:Key="Almond-Creme-Brush"
    50. Color="#FFffbbaa" />
    51. <SolidColorBrush
    52. x:Key="Sunflower-Brush"
    53. Color="#FFFFCC66" />
    54. <SolidColorBrush
    55. x:Key="Bluey-Brush"
    56. Color="#FF7788ff" />
    57. <SolidColorBrush
    58. x:Key="Gray-Brush"
    59. Color="#FF666688" />
    60. <SolidColorBrush
    61. x:Key="Sky-Brush"
    62. Color="#FFaaaaff" />
    63. <SolidColorBrush
    64. x:Key="Ice-Brush"
    65. Color="#FF88ccff" />
    66. <SolidColorBrush
    67. x:Key="Gold-Brush"
    68. Color="#FFffaa00" />
    69. <SolidColorBrush
    70. x:Key="Mars-Brush"
    71. Color="#FFff2200" />
    72. <SolidColorBrush
    73. x:Key="Peach-Brush"
    74. Color="#FFff8866" />
    75. <SolidColorBrush
    76. x:Key="Butterscotch-Brush"
    77. Color="#FFff9966" />
    78. <SolidColorBrush
    79. x:Key="Tomato-Brush"
    80. Color="#FFff5555" />
    81. <SolidColorBrush
    82. x:Key="Lilac-Brush"
    83. Color="#FFcc33ff" />
    84. <SolidColorBrush
    85. x:Key="Links-Brush"
    86. Color="#FFcc33ff" />
    87. <!-- LCARS Classic Theme END -->
    88. </Application.Resources>
    89. </Application>


    Das ist meine Ablage für Farben, in Form von "SolidColorBrushes".

    Das sollte wenn möglich in "MergedDictionaries" organisiert werden.

    Hier ein Beispiel mit Ordnern per "Vorlagen-Typen",
    Ist nicht vorgeschrieben wie, aber so wurde das damals von mir Organisiert.

    Die Datei "UIStyling.xaml" enthält nur Referenzen zu anderen "MergedDictionaries".

    XML-Quellcode

    1. <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    2. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    3. <ResourceDictionary.MergedDictionaries>
    4. <ResourceDictionary Source="Colors/Colors.xaml" />
    5. <ResourceDictionary Source="Colors/Brushes.xaml" />
    6. <ResourceDictionary Source="VectorGraphics/Icons.xaml" />
    7. <ResourceDictionary Source="Images/Images.xaml" />
    8. <!--<ResourceDictionary Source="UISettings/Typography.xaml" />-->
    9. <ResourceDictionary Source="Styles/CheckBox.xaml" />
    10. <ResourceDictionary Source="Styles/Button.xaml" />
    11. <ResourceDictionary Source="Styles/ToggleButton.xaml" />
    12. <ResourceDictionary Source="Styles/ComboBox.xaml" />
    13. <ResourceDictionary Source="Styles/ListBox.xaml" />
    14. <!--<ResourceDictionary Source="Styles/Expander.xaml" />-->
    15. <ResourceDictionary Source="Controls/ComboBox.xaml" />
    16. </ResourceDictionary.MergedDictionaries>
    17. </ResourceDictionary>


    Bitte bedenke, das diese Sturktur voll "Overpowered" ist.

    Es reicht ja sich mit dem möglichkeiten vom "Darkmode" als Theme auswahl anzlesen, und schon finden sich online viele "Frameworks" zu diesem Thema.

    Frage an Alle: "Ist es ein Oximoron, wenn Theme-ing das Thema ist?" :)

    Es ist viel einfacher die Windows Standardfarben einfach zu überschreiben.

    z.B.: "ActiveBorderBrushKey" ist ein Systemweite Resource, und es ist möglich diese in seiner/Ihrer Application.xaml einfach festzulegen.

    "MahApps" kann ich nur einmal erwähnen, ich selber nutze das nicht, abr die haben schon viele vorlagen und es ist einfach zu nutzen.

    c.u. Joshi, muss jetzt Anno spielen...

    kafffee schrieb:

    nicht versteh, fängt schon an bei ViewModel und MVVM...
    Tja, das sind aber die Grundbausteine von Wpf.
    Ich glaube auch, mit den Grundlagen-Artikeln im wpf-Bereich lassen sich die erschliessen.
    Ansonsten googlen.
    Ohne einen Begriff von ViewModel und MVVM zu haben ist wpf eine ziemlich abstruse Ansammlung von Kinderkrankheiten und irrwitzig umständlich.
    Vielleicht lassen sich ein paar Klicki-Bunti-Effekte zusammenfrickeln, aber das ists nicht wert, um dafür vom erprobten und sinnvollen WinForms abzugehen.

    Wie gesagt: Control-Farben programmweit festlegen - das geht auch in Winforms, und ohne solche Hirn-Brecher wie

    VB.NET-Quellcode

    1. Resources("Skin") = New SolidColorBrush(CType(lstColors.SelectedItem, Color))
    Also für den aktuellen Moment würde es mir reichen, zu wissen, was man in Zeile 3 von meinem Post #1 schreiben muss. Hab mir jetzt stundenlang einen abgegoogelt, aber das bringt nicht viel wenn man nicht wirklich weiss nach welchem Begriff man suchen soll...

    Ich hoffe das ist so einfach wie ich denke.

    Bin eher der Learning-By-Doing-Typ.
    Hi.

    Kein schliessendes Tag. Dafür aber, einen Wert beim Attribut "Color" setzen...

    XML-Quellcode

    1. <SolidColorBrush
    2. x:Key="Space-White-Brush"
    3. Color="#FFf5f6fa" />


    Oder so...

    XML-Quellcode

    1. <SolidColorBrush
    2. x:Key="Space-White-Brush"
    3. Color="#FFf5f6fa" >
    4. </SolidColorBrush>



    <SolidColorBrush x:Key="Skin">

    </SolidColorBrush>
    <-- Wird zu -->

    <SolidColorBrush x:Key="Skin" Color="#FFAABBCC" />




    :)

    c.u. Joshi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Joshi“ () aus folgendem Grund: Direkte Lösung des Themas angefügt, mit Beispiel.

    Hi.


    In einer ListBox wird eine "Collection" vorgehalten, und mittels "CollectionSource" als referenz angegeben wird.

    Diese kann alle möglich Typen/Objekttypen enthalten, und diese muss dann nur der ListBox mitgeteilt werden wie die elemente gezeichent werden sollen.

    "DataTemplate" ist hier das Stichwort. Klingt kompliziert, ist es beim erstenmal auch...

    Also eine Sammlung von SodilColorBrushes (als Beispiel) und diese dann auswählen. Dann muss noch das ausgewählte Element (was ja ein Objekt/SolidColorBrush ist)
    wiederverwendet werden.

    Das ist eigenlich voll einfach, es bedarf aber mehrer Komponeneten die da hineispielen.

    Eine ist die Quelle der Elemente. (Sammlung/Collection/ObservableCollection etc.)
    Dann das Ausgewählte Element dieser Sammlung. (SelectedItem, nicht SelectedIndex)
    Dann das behandeln, des zur Zeit ausgewählten Elementes. (Dann die Farbe deines/er Control(s) ändern.)

    Sammmlung, Auswahl in einer Sammlung, Ereignisbehandlung der Auswahl...

    Das ist der Vorgang.

    Ist nicht schwer, aber hier ist das Learning bei Doing nicht einfach möglich.

    c.u. Joshi
    @Joshi

    OK. Meine Listbox sieht so aus:

    XML-Quellcode

    1. <ListBox Name="lstColors" Height="200" Width="200" SelectionChanged="lstColors_SelectionChanged" SelectionMode="Single">
    2. <ListBox.ItemTemplate>
    3. <DataTemplate>
    4. <ListBoxItem Width="130" Content="{Binding ColorName}"/>
    5. </DataTemplate>
    6. </ListBox.ItemTemplate>
    7. </ListBox>


    Ich glaube das was du meinst mit Collection und CollectionSource ist hier bei mir anders gelöst. Also anstelle Collection --> ListBoxItem und anstelle CollectionSource hier Content. Sehe ich das richtig?

    Dann hab ich eine Klasse ColorInfo mit der Eigenschaft ColorName As String und eine Dim color_query As IEnumerable(Of ColorInfo), die logischerweise dann sowas wie eine Liste mit den Farben enthält.

    Ich weise die Liste dann der ListBox zu mit: lstColors.ItemsSource = color_query

    Das wäre dann logischerweise die Quelle.

    Das ausgewählte Element wäre dann lstColors.SelectedItem.

    Alles richtig soweit?

    Wo es jetzt bei mir hapert ist denke ich dann das Behandeln des ausgewählten Elementes und die Farbe der Controls ändern.

    Ich hab das jetzt mit...:

    VB.NET-Quellcode

    1. Private Sub lstColors_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles lstColors.SelectionChanged
    2. Resources("Skin") = New SolidColorBrush(CType(ColorConverter.ConvertFromString(color_query(lstColors.SelectedIndex).ColorName), Color))
    3. End Sub

    ...gelöst. Was ja gut ist, aber das hätte ich doch bestimmt dann auch irgendwo in den XAML-Code schreiben können oder?

    kafffee schrieb:

    Hab mir jetzt stundenlang einen abgegoogelt, aber das bringt nicht viel wenn man nicht wirklich weiss nach welchem Begriff man suchen soll...
    Hmm - die Begriffe hast du doch selbst ins Spiel gebracht: Viewmodel, MVVM.


    kafffee schrieb:

    Also für den aktuellen Moment würde es mir reichen, zu wissen, was man in Zeile 3 von meinem Post #1 schreiben muss...
    Ich hoffe das ist so einfach wie ich denke.
    Ist es nicht.
    Es ist anders einfach als auf dem Holzweg, auf dem du grade bist.
    Du musst zurück zum Start, und nochmal loslaufen, diesmal in Richtung Viewmodel, MVVM.

    Ansonsten Wunderts mich, dass die Sascha-Videos dazu nix beitragen. Ich hab die aber auch nur zum ganz kleinen Teil geguckt, und auch vor langem.
    Du kannst dich an meine Teile halten, die bauen alle auf Viewmodel, MVVM auf.
    Fang mit BindingPicking an, gugge auch Treeview - ich glaub da ist auch ein Link auf Josh Smith's Grundsatz-Artikel.
    Dann gugge Anwendungsstruktur.
    Dann gugge den Link, den ich dir in Post#2 gegeben habe - das ist die einfachste Lösung, eine Listbox-Auswahl anwendungsweit bekannt zu machen: Nämlich indem sie an eine ListCollectionView im Viewmodel gebunden ist.

    Bei mir wird alles über Viewmodel abgewickelt, mit Databinding und DataTemplates.
    Kann sein, dassich es ein bischen gewandelt hab im Lauf der Zeit: Früher hab ich eine Mainviewmodel-Instanz inne App.Xaml-Resources hinterlegt, und alles daran gebunden.
    Heutzutage binde ich eher an eine Public Shared MainViewmodel-Instanz direkt im Viewmodel. Aber das Prinzip dasselbe.

    Also am Begriff Viewmodel kommst du nicht vorbei (doch, natürlich, aber werweiss, wohin das führt).



    Ich kann auch eine MinimalDefinition des Konzepts versuchen:
    • Control-Events spielen in Wpf keine Rolle mehr - alles wird über Databinding abgefackelt.
      Daher ist dein post#3 so daneben.
    • Das Viewmodel ist ein Sammelsurium miteinander verbundener Klassen, die die komplette Logik der Anwendung abbilden.
      Im Viewmodel kommen keine Controls vor, oder ihre Events.
    • Controls sind ausschliesslich im Xaml vorhanden. Und die einzige Verbindung zwischen Controls und Viewmodel sind die Bindings.
    • Das Viewmodel ist komplett unabhängig von den Controls im Xaml. Also man könnte das Xaml wegnehmen - kompilieren würde die Anwendung ebensogut. (nur könnte sie nix tun, weils keine User-Interaktion gibt, die - via Bindings - ins Viewmodel hineinwirkt)
    Das ganze hat bischen was von einer Avatar - Avatar-User - Beziehung: Der Avatar ist wie ein (prinzipiell auch austauschbarer) Anzug, den der User anlegt, und der ihm Sinnesorgane und auch Wirk-Möglichkeiten innerhalb der Avatar-Welt verleiht.
    Oder wie son SciFi-kraft-verstärkender Anzug: Der Anzug folgt den Bewegungen des Insassen und verstärkt sie, ausserdem liefert er Sinneseindrücke von aussen.
    Und die Schnallen, knöpfe, Reissverschlüsse und Schnürsenkel des Anzugs - das sind die Bindings.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Ja, ich nehme die Arbeit auch gerade wieder auf, die ersten zwei Kapitel sind soweit von den Videos her fertig, aber die Texte fehlen mir noch.
    Es geht aber weiter.

    Grüße
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##