StyleVerhalten, das ich nicht nachvollziehen kann & WPF-Styles, die mich in den Wahnsinn treiben

  • WPF

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von PadreSperanza.

    StyleVerhalten, das ich nicht nachvollziehen kann & WPF-Styles, die mich in den Wahnsinn treiben

    Hallo Leute,

    ich bin nun wieder hier... und langsam sollte ich mir überlegen, einen Sammelthread aufzumachen, in dem ich dann alle meine Style-Probleme schildere. Ich komme mittlerweile mit dem Styling einigermaßen klar und es macht auch immer mehr Spaß. Leider kommt man sich an manchen Stellen auch immer mal wieder in die Quere. Und so fällt mir auch das nun auf die Füße:

    Ich habe ein DatePicker genommen und dessen Style überarbeitet, damit es zum Design passt. Das passt und funktioniert nun auch wirklich wunderbar. Leider hat dieser Style Auswirkungen auf die Scrollbar und färbt diese mit ein. Und ich habe echt alles doppelt und dreifach abgesucht, auch geschaut, ob irgendwo Namen oder Klassen gleich sind, aber ich finde einfach nicht heraus, warum der DatePickerStyle in den Style des ScrollBars hineingreift, zumal ich beide eigtl sogar mit Key anrede. Die Styles sind allerdings in Style-Resourcenverzeichnisse ausgelagert:

    Ich hatte erst die Styles hier einbinden wollen, aber bei 50k Zeichen ist Schluss, also habe ich die Dateien jeweils als Anhang beigefügt für: DatePicker, Calendar, ScrollBar, ListView. In den Dateien für Calendar und Scrollbar habe ich auch die beiden Zeilen markiert, die betroffen sind (meiner Meinung nach) und das Verhalten auslösen. auch wenn ich nicht verstehe warum das so ist.

    In Calendar ist es Zeile 466, die ColorAnimation
    Scrollbar Zeile 136

    Die ListView wird so eingebunden:

    Spoiler anzeigen

    XML-Quellcode

    1. <DockPanel DataContext="{StaticResource ViewModelContract}" Grid.Column="0">
    2. <TextBox DockPanel.Dock="Top" Style="{StaticResource SearchBox}"/>
    3. <TextBlock Text="Aufträge:" DockPanel.Dock="Top" HorizontalAlignment="Center" FontWeight="DemiBold" FontSize="24"/>
    4. <ListView ItemsSource="{Binding CollectionView}" x:Name="ContractListView" DockPanel.Dock="Top"
    5. Background="Transparent" ItemContainerStyle="{StaticResource MouseOverKey}"
    6. >
    7. <ListView.ItemTemplate>
    8. <DataTemplate>
    9. <StackPanel Background="{Binding DesiredDate, Converter={StaticResource DatePickerBackgroundConverter}}" >
    10. <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
    11. <StackPanel.Resources>
    12. <System:String x:Key="redKey">red</System:String>
    13. <System:String x:Key="yellowKey">yellow</System:String>
    14. <System:String x:Key="greenKey">green</System:String>
    15. </StackPanel.Resources>
    16. <Ellipse Width="10" Height="10" StrokeThickness="1" Stroke="Black">
    17. <Ellipse.Fill>
    18. <MultiBinding Converter="{StaticResource StatusMultiConverter}">
    19. <Binding Path="Status"/>
    20. <Binding Source="{StaticResource redKey}" />
    21. <Binding Source="{x:Static model:WorkProgressStatus.NotStartet}"/>
    22. </MultiBinding>
    23. </Ellipse.Fill>
    24. </Ellipse>
    25. <Ellipse Width="10" Height="10" StrokeThickness="1" Stroke="Black">
    26. <Ellipse.Fill>
    27. <MultiBinding Converter="{StaticResource StatusMultiConverter}">
    28. <Binding Path="Status"/>
    29. <Binding Source="{StaticResource yellowKey}" />
    30. <Binding Source="{x:Static model:WorkProgressStatus.WorkInProgress}"/>
    31. </MultiBinding>
    32. </Ellipse.Fill>
    33. </Ellipse>
    34. <Ellipse Width="10" Height="10" StrokeThickness="1" Stroke="Black">
    35. <Ellipse.Fill>
    36. <MultiBinding Converter="{StaticResource StatusMultiConverter}">
    37. <Binding Path="Status"/>
    38. <Binding Source="{StaticResource greenKey}" />
    39. <Binding Source="{x:Static model:WorkProgressStatus.ReadyForDelivery}"/>
    40. </MultiBinding>
    41. </Ellipse.Fill>
    42. </Ellipse>
    43. </StackPanel>
    44. <TextBlock Text="{Binding OrderNumber}" FontWeight="ExtraBlack"/>
    45. <TextBlock Text="{Binding Customer.Lastname}"/>
    46. <TextBlock Text="{Binding OrderDate}" Margin="10"/>
    47. </StackPanel>
    48. </DataTemplate>
    49. </ListView.ItemTemplate>
    50. </ListView>
    51. </DockPanel>



    Das Designen macht mir echt Laune, und ich möchte auch echt verstehen, was das Problem ist... aber manchmal habe ich das Gefühl, dass WPF und XAML durchaus komplexer sind als gedacht, oder ich einfach unfähig bin (vielleicht ja auch beides)

    Ich habe heute den halben Tag damit verbracht, mir die Styles nochmal anzuschauen und weiß nicht, wo das Problem liegt... vielleicht hat ja jemand von euch eine Idee oder weiß, woran es liegen könnte.

    PS: Den Inhalt in der ListView braucht man hier eher nicht beachten, da es nur ums reine Design der Scrollbar geht. Der Rest ist wunderbar in Ordnung, deshalb habe ich Klassen, Konverter und ViewModel erstmal außen vor gelassen


    Wenn das so weiter geht, ist der Wahnsinn bei mir nahe 8| 8| 8|
    Bilder
    • normal.png

      14,56 kB, 446×360, 55 mal angesehen
    • MouseOver.png

      15,52 kB, 476×366, 56 mal angesehen
    Dateien
    • Calendar.xaml

      (39,29 kB, 77 mal heruntergeladen, zuletzt: )
    • Colors.xaml

      (2,68 kB, 38 mal heruntergeladen, zuletzt: )
    • DatePicker.xaml

      (20,91 kB, 75 mal heruntergeladen, zuletzt: )
    • ListView.xaml

      (194 Byte, 50 mal heruntergeladen, zuletzt: )
    • ScrollBar.xaml

      (14,23 kB, 62 mal heruntergeladen, zuletzt: )

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

    Hallo,
    ich kann den Effekt nicht reproduzieren.
    Hab dir mal ein TestProjekt angehangen wie ich es getestet habe. Bei dir scheint es noch andere Sachen zu geben die da eingreifen.
    Ein paar mehr Infos oder ein kleines Projekt von dir wo man den Fehler nachstellen kann wäre hier Hilfreich.

    Wird bei dieser Codezeile das Model in die View geholt? Die Benamung lässt dies vermuten.

    XML-Quellcode

    1. ​<Binding Source="{x:Static model:WorkProgressStatus.WorkInProgress}"/>
    Dateien
    • TestProjekt00.zip

      (2,19 kB, 42 mal heruntergeladen, zuletzt: )
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.
    ja, ich bin auch schon die ganze Zeit am Rätsel-Raten... ich konnte mir bisher auch nicht erklären, warum das Einfluss auf die Scrollbar hat. weder der x:Name noch andere Dinge passen eigentlich zu diesem Verhalten. deshalb bin ich irritiert. Ich kann gerne versuchen, die Tage mal das Projekt anzuhängen und die Testdaten zu entfernen.

    Zu deiner Frage: Nicht ganz. Ich habe im Ordner "Model" auch eine Datei angelegt, die alle notwendigen Enums verwaltet. WorkProgressStatus ist ein Enum und WorkInProgress ist ein explizierter Wert von WorkProgressStatus. Diesen gebe ich als Parameter mit, um auf das Enum zu testen und bedingt davon den Background einzufärben.
    Ich habe dort eine Ampel, die von rot auf gelb auf grün schaltet. der Code ist aber auch nur erstmal dahingeschmiert worden, um zu zeigen, dass es möglich ist. Hat aber mit dem eigentlichen Problem leider nichts zu tun.
    Ich komme tatsächlich nicht weiter. Ich habe hier im Anhang das Projekt angefügt und sehe einfach nicht, warum es Auswirkung hat. Vielleicht mag ja nochmal jemand rüberschauen.

    Aufgrund der maximalen Größe von Anhängen musste ich das Archiv leider teilen.
    Dateien
    Hallo

    Das Problem ist das du so gut wie nur mit DynamicResources arbeitest und nicht mit StaticResources.
    Dynamische Resourcen haben eben den Vorteil das dies zur Laufzeit geändert werden können. (Theming)
    Aber wenn ich das richtig sehe ist das in deinem Fall ja nicht mal gewollt. Als wozu? aber OK.

    Du hast also diverse Referenzen(!!) auf eine Color und/oder eine Brush gesetzt, und veränderst dann hier den Wert:

    XML-Quellcode

    1. <VisualState x:Name="MouseOver">
    2. <Storyboard>
    3. <ColorAnimation Duration="0:0:2" From="{DynamicResource LightAcent}"
    4. To="Green"
    5. Storyboard.TargetProperty="(TextElement.Foreground).
    6. (SolidColorBrush.Color)"
    7. Storyboard.TargetName="buttonContent" />
    8. </Storyboard>
    9. </VisualState>

    (Nicht wundern, ich habe die Animation zum testen abgeändert.)

    Setze mal zum spass den Background des MainWindow-TabControl auf ​Background="{DynamicResource LightAcentBrush}"
    Du siehst das auch hier der Hintergrund dann plötzlich (in meinem Test) Grün wird.

    Du veränderst also die DynamicResource (dessen Color-Wert).
    Warum? Weil du eine Referenz auf dieses eine Objekt gesetzt hast und dieses veränderst.
    Abhilfe schafft hier die Resource als Shared zu deklarieren. Damit bekommst du für jedes mal wenn es verwendet wird quasi eine kopie.

    XML-Quellcode

    1. ​<Color x:Shared="False" x:Key="LightAcent">Lightgray</Color>
    2. <SolidColorBrush x:Shared="False" x:Key="LightAcentBrush" Color="{DynamicResource LightAcent}"/>


    Nicht wundern bitte. False bedeutet in diesem Fall true. Also wenn der Wert ​False ist dann ist es Shared.
    Frag mich bitte nicht warum MS das so gemacht hat.

    Grüße
    Sascha
    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. ##

    Okay, das heißt also: Ich lag gar nicht falsch damit, dass die Styles sich nicht gegenseitig beeinflussen (jedenfalls nicht direkt), da sie auch keinen direkten Bezug zueinander haben, sondern durch die dynamicResource kommt das ganze zustande? Okay, wow... das ist tatsächlich wieder etwas Neues, auf das man achten muss.

    Nun habe ich hierzu tatsächlich noch ein paar Fragen, und hoffe, du kannst sie vielleicht auch beantworten: Da ich die Farben ja als Color definieren möchte, um nicht jedes Mal überall die Farbwerte manuell zu ändern, habe ich sie in Color.xaml ausgelagert. Wenn ich sie nun in den Styles aber verwenden möchte, so geht dies nur, wenn ich sie als DynamicResource einbinde. Wenn ich StaticResource nutze, dann motzt VS beim starten. Das war auch der Grund, warum ich sie alle als dynamisch hinzugefügt habe. Wenn ich sie als StaticResource hinzufügen möchte, müsste ich ja jedem Style die Farben in derselben Datei bekanntmachen? Order habe ich hier wieder eine Möglichkeit übersehen?

    Das zweite, das ich hier nicht verstehe: Ich dachte, wenn ich ein StoryBoard verwende und dort die TargetProperty zB auf (TextElement.Foreground).(SolidColorBrush.Color) from a To b ändere, würde eben der Farbwert für eben diese Eigenschaft geändert. Wenn ich dich nun aber richtig verstanden habe (korrigiere das bitte gern), dann ändere ich damit nicht den Wert der Eigenschaft, sondern ich ändere damit den Wert, der sich in der DynamicResource befindet?

    Ja, Theming ist etwas, das ich noch hinzufügen wollte (das ist ja alles noch im Rohbau). Aber bevor ich mich daran wagen wollte, wollte ich eigtl erstmal einen Style (oder theme) fertig haben. Das heißt also, wenn ich dem Nutzer die Möglichkeit geben möchte, das Theme zu ändern, muss ich wieder mit DynamicResource arbeiten?

    Und um das nun abzurunden mit der Fragestunde: Wenn ich das nun als Shared definiere, dann tritt das Verhalten nicht mehr auf - aber dann kann ich auch kein Themeing bereitstellen, da ich es dann ja sozusagen "sperre". Das heißt: Am besten wäre es, wenn ich für alle Bereiche oder Styles jeweils eine eigene DynamicResource bereitstelle, also zB sowas:

    XML-Quellcode

    1. <Color x:Key="ScrollBarLightAcent"> Lightgray</Color>
    2. <Color x:Key="CalendarLightAcent">Lightgray</Color>
    3. ...


    Um jedem Control dann einen eigenen Verweis zu geben, damit sie sich nicht gegenseitig in die Quere kommen und ich sie danach (wenn ich sie nicht shared haben möchte) auch dynamisch zur Laufzeit ändern kann, um andere Themes bereitzustellen?

    Habe ich das insoweit richtig aufgefasst, oder gibt es hier eine noch bessere oder gar edlere Lösung :)

    Auf jeden Fall hast du mir wieder einmal aus der Patsche geholfen, @Nofear23m / Sascha :) Ich habe die Styles noch und nöcher durchgeschaut und habe mir nicht erklären können, was mein Fehler ist.

    Grüße Pascal
    OK, das sind recht viele Fragen auf einmahl.

    PadreSperanza schrieb:

    Wenn ich sie nun in den Styles aber verwenden möchte, so geht dies nur, wenn ich sie als DynamicResource einbinde. Wenn ich StaticResource nutze, dann motzt VS beim starten.

    Ja, weil du die Styles in der App.xaml definierst müssen diese Dynamic sein. Macht aber nix. Die Grundregel ist einfach: Da wo es geht StaticResource und nur wenns nicht geht dann DynamicResource.

    PadreSperanza schrieb:

    wenn ich ein StoryBoard verwende und dort die TargetProperty zB auf (TextElement.Foreground).(SolidColorBrush.Color) from a To b ändere, würde eben der Farbwert für eben diese Eigenschaft geändert.

    Es wird die Referenz des Farbwerts geändert und nichts anderes. Shared macht nichts anderes als immer eine Kopie des Styles zu erstellen, und damit kann der Style dann nicht mehr von außen beeinflußt werden.
    Kann man fast so sehen als würde die WPF hingehen und ein LightAcent1, ein LightAcent2, ein LightAcent3,...... machen.

    PadreSperanza schrieb:

    Das heißt also, wenn ich dem Nutzer die Möglichkeit geben möchte, das Theme zu ändern, muss ich wieder mit DynamicResource arbeiten?

    Jep

    PadreSperanza schrieb:

    aber dann kann ich auch kein Themeing bereitstellen, da ich es dann ja sozusagen "sperre".

    Ne, ist egal, siehe oben.

    Grüße
    Sascha
    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. ##