WPF ContentControl / Eigenschaften nach außen / Vorlage

  • WPF
  • .NET (FX) 4.5–4.8

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von DTF.

    WPF ContentControl / Eigenschaften nach außen / Vorlage

    Hallo!

    Ich versuche gerade in WPF einen Jahreskalender zu erstellen.
    Dafür benötige ich eine Vorlage/Template für den Tag im Kalender.
    Ich hab mir schon bissl was zusammengebastelt, aber ich kann jetzt über ContentControl nicht auf die Eigenschaften der einzelnen Controls im Template zugreifen.

    Spoiler anzeigen

    XML-Quellcode

    1. <Window x:Class="MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:local="clr-namespace:Excel_WPF_Test"
    7. mc:Ignorable="d"
    8. Title="MainWindow" Height="450" Width="800">
    9. <Grid>
    10. <Grid.Resources>
    11. <DataTemplate x:Key="Template1">
    12. <Grid>
    13. <Grid.ColumnDefinitions>
    14. <ColumnDefinition Width="100"/>
    15. <ColumnDefinition Width="100"/>
    16. <ColumnDefinition Width="200"/>
    17. <ColumnDefinition Width="30"/>
    18. </Grid.ColumnDefinitions>
    19. <Grid.RowDefinitions>
    20. <RowDefinition Height="20"/>
    21. <RowDefinition Height="20"/>
    22. <RowDefinition Height="20"/>
    23. <RowDefinition Height="20"/>
    24. </Grid.RowDefinitions>
    25. <Label x:Name="Datum"
    26. Grid.Row="0"
    27. Grid.Column="0"
    28. Grid.RowSpan="4"
    29. Content="01"
    30. HorizontalAlignment="Center"
    31. VerticalAlignment="Center"
    32. FontSize="20">
    33. </Label>
    34. <Label x:Name="Tag"
    35. Grid.Row="0"
    36. Grid.Column="1"
    37. Grid.RowSpan="4"
    38. Content="Mo"
    39. FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    40. <Label x:Name="Feiertag"
    41. Grid.Row="0"
    42. Grid.Column="2"
    43. Grid.RowSpan="2"
    44. Grid.ColumnSpan="2"
    45. Content="Feiertag"
    46. FontSize="20"/>
    47. <Label x:Name="Termin"
    48. Grid.Row="2"
    49. Grid.Column="2"
    50. Grid.RowSpan="2"
    51. Grid.ColumnSpan="2"
    52. Content="Termin"
    53. FontSize="20"/>
    54. <Label x:Name="Woche"
    55. Grid.Row="0"
    56. Grid.Column="3"
    57. Content="Wo1"
    58. FontSize="8"
    59. Panel.ZIndex="1"/>
    60. </Grid>
    61. </DataTemplate>
    62. </Grid.Resources>
    63. <Grid.ColumnDefinitions>
    64. <ColumnDefinition />
    65. </Grid.ColumnDefinitions>
    66. <Grid.RowDefinitions>
    67. <RowDefinition/>
    68. <RowDefinition/>
    69. <RowDefinition/>
    70. <RowDefinition/>
    71. </Grid.RowDefinitions>
    72. <Button Grid.Column="0"
    73. Grid.Row="1"
    74. Background="LightBlue"
    75. Height="100">
    76. <ContentControl Name="contCtrl"
    77. ContentTemplate="{StaticResource Template1}"
    78. Content="This is the content of the content control."
    79. HorizontalAlignment="Center"
    80. VerticalAlignment="Center"
    81. />
    82. </Button>
    83. </Grid>
    84. </Window>



    Ich brauche für jedes Label im Template ein Zugriff auf die Content bzw. Text Eigenschaft um diese dann im Jahreskalender anzupassen.
    Nabn'd :)

    Wie ich sehe, ist der Content belegt.
    Ist das nicht der Grund, ein ContentControl mit (mehr) Inhalt (Controls) zu befüllen?

    Quellcode

    1. Content="This is the content of the content control."
    ?(

    Ist schon Mitternacht, was weiß ich denn um diese Uhrzeit?

    c.u. Joshi :D
    Das alles so in die Ressourcen auszulagern, ist etwas prekär und scheint hier wirklich etwas Zusammengewürfeltes aus diversem Code zu sein. Ich habe den XAML-Inhalt mal spaßhalber in einem leeren WPF-Projekt eingefügt, um zu sehen, was eigentlich auf dem Bildschirm – und vor allem wie – dargestellt wird. Normalerweise bleiben die Elemente Button, Label, TextBlock im Hauptcode und ausgelagert wird der Style oder Template, so wie in diesem Beispiel unten – man muss nicht immer alles komplizierter und sich dadurch das Leben unnötig schwer machen als es eh schon ist, wenn man auf einfacherem Wege etwas Vergleichbares oder gar Identisches erreichen kann. Was genau soll dieser Kalender denn so können oder sich ungewöhnlich verhalten, dass man das so verwringt machen muss? Was soll in dem Layout zur Laufzeit änderbar sein?

    XML-Quellcode

    1. <Button x:Name="btn_OK" Template="{DynamicResource btnTemplate_All}" Style="{StaticResource btn_All}" Content="OK" Width="65" Height="33" Margin="15,10,10,15" IsDefault="True" />
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.

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

    Morrison schrieb:

    aber ich kann jetzt über ContentControl nicht auf die Eigenschaften der einzelnen Controls im Template zugreifen.


    ja. das soll man ja auch garnet.
    In Wpf hat man ein Viewmodel, und greift auf Eigenschaften des Viewmodels zu.
    Ans Viewmodel gebunden ist dann ein in Xaml gecodetes View. Auf dessen Eigenschaften greift man nie zu.



    Vielleicht will Joshi ja auch darauf hinaus, wenn er sagt, ein ContentControl.Content belegt man normal mit mehr Inhalt als mit einem String.
    Nämlich da gehört ein Binding ans Viewmodel hinein, und für das Binding soll es in den Resourcen ein DataTemplate geben.

    Aber ich weiss garnet, inwieweit dir der MVVM-Pattern bekannt ist...
    Ohne den macht es nicht viel Sinn, Wpf zu programmieren...

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

    Vielleicht hilft diese Information auch etwas weiter: es gibt außer dem Grid – der einem von Visual Studio als default immer in WPF vor die Nase geklatscht wird, bei dem Leute dann oft „hängenbleiben” und manchmal dann komische Dinge damit veranstalten, um etwas auf dem Bildschirm darzustellen – auch noch andere Panelelemente, die entweder genauso wie das Grid direkt an das Window angeknüpft oder auch fast beliebig untereinander kombiniert werden können. Die KontrollElemente und alles, was so da drin sich befindet, sind durchaus in der Lage, sich selbst auszurichten und mit vordefinierten Prozentangaben sogar die richtige Position und Breite anzunehmen, ohne explizit immer manuell die Reihen und Zeilen durchexerzieren und angeben zu müssen – so'ne Woche vom Kalender kann man damit bestimmt automatisch einfach so einblenden, vielleicht sogar einen ganzen Monat. Man muss sich allerdings etwas Zeit nehmen und ein wenig damit herumexperimentieren, bis man das gewünschte Puzzle findet und auch anwenden kann (es kann sein, dass ich was vergessen und es nicht erwähnt habe):
    • Grid – jou, kennen wir ja schon
    • UniformGrid – eine Sonderform von Grid
    • StackPanel – wie der Name schon sagt, kann man hier etwas stapeln – sowohl horizontal als auch vertikal
    • WrapPanel – ähnlich wie Stackpanel, nur dass hier Elemente umgeschlagen werden können
    • DockPanel – zum Andocken links, rechts, oben und unten – damit kann man auch sehr schöne Kreationen in Verbindung mit z.B. Stackpanel auf dem Fenster schaffen
    • Canvas – für absolute Pixelangaben auf dem Tisch genau das richtige Ding
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.
    OK, musste mich da erstmal bissl reinlesen! ^^

    Habs bis jetzt so:
    KalendertagControl-View:
    Spoiler anzeigen

    XML-Quellcode

    1. <UserControl x:Name="Kalendertag"
    2. x:Class="KalendertagModel"
    3. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    4. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    7. xmlns:local="clr-namespace:WPF_Kalender_01"
    8. xmlns:vm="clr-namespace:WPF_Kalender_01.ViewModels"
    9. mc:Ignorable="d"
    10. d:DesignHeight="77.508"
    11. d:DesignWidth="392.893">
    12. <UserControl.DataContext>
    13. <vm:KalendertagModel />
    14. </UserControl.DataContext>
    15. <Grid x:Name="ctrlGrid"
    16. Width="{Binding ActualWidth, ElementName=userControl, Mode=OneWay}"
    17. Height="{Binding ActualHeight, ElementName=userControl, Mode=OneWay}">
    18. <Grid.ColumnDefinitions>
    19. <ColumnDefinition />
    20. </Grid.ColumnDefinitions>
    21. <Grid.RowDefinitions>
    22. <RowDefinition/>
    23. </Grid.RowDefinitions>
    24. <Button x:Name="button" Grid.Column="0"
    25. Grid.Row="0"
    26. Background="LightBlue"
    27. HorizontalAlignment="Center"
    28. VerticalAlignment="Center"
    29. Height="{Binding ActualHeight, ElementName=grid, Mode=OneWay}"
    30. Width="{Binding ActualWidth, ElementName=grid, Mode=OneWay}">
    31. <Grid x:Name="btnGrid"
    32. Width="{Binding ActualWidth, ElementName=button, Mode=OneWay}"
    33. Height="{Binding ActualHeight, ElementName=button, Mode=OneWay}"
    34. HorizontalAlignment="Center"
    35. VerticalAlignment="Center">
    36. <Grid.ColumnDefinitions>
    37. <ColumnDefinition x:Name="Col1" Width="100*"/>
    38. <ColumnDefinition x:Name="Col2" Width="100*"/>
    39. <ColumnDefinition x:Name="Col3" Width="200*"/>
    40. <ColumnDefinition x:Name="Col4" Width="30*"/>
    41. </Grid.ColumnDefinitions>
    42. <Grid.RowDefinitions>
    43. <RowDefinition x:Name="Row1" Height="20*"/>
    44. <RowDefinition x:Name="Row2" Height="20*"/>
    45. <RowDefinition x:Name="Row3" Height="20*"/>
    46. <RowDefinition x:Name="Row4" Height="20*"/>
    47. </Grid.RowDefinitions>
    48. <Viewbox x:Name="vbDatum"
    49. Grid.Row="0"
    50. Grid.Column="0"
    51. Grid.RowSpan="4">
    52. <Label x:Name="sDatum"
    53. FontSize="20"
    54. HorizontalContentAlignment="Center"
    55. VerticalContentAlignment="Center"
    56. HorizontalAlignment="Stretch"
    57. VerticalAlignment="Stretch"
    58. Content="{Binding Datum}"/>
    59. </Viewbox>
    60. <Viewbox x:Name="vbTag"
    61. Grid.Row="0"
    62. Grid.Column="1"
    63. Grid.RowSpan="4">
    64. <Label x:Name="sTag"
    65. FontSize="20"
    66. HorizontalContentAlignment="Center"
    67. VerticalContentAlignment="Center"
    68. HorizontalAlignment="Stretch"
    69. VerticalAlignment="Stretch"
    70. Content="{Binding Tag}">
    71. </Label>
    72. </Viewbox>
    73. <Viewbox x:Name="vbFeiertag"
    74. Grid.Row="0"
    75. Grid.Column="2"
    76. Grid.RowSpan="2"
    77. Grid.ColumnSpan="2"
    78. HorizontalAlignment="Left"
    79. VerticalAlignment="Top">
    80. <Label x:Name="sFeiertag"
    81. FontSize="20"
    82. HorizontalContentAlignment="Left"
    83. VerticalContentAlignment="Top"
    84. Content="{Binding Feiertag}">
    85. </Label>
    86. </Viewbox>
    87. <Viewbox x:Name="vbTermin"
    88. Grid.Row="2"
    89. Grid.Column="2"
    90. Grid.RowSpan="2"
    91. Grid.ColumnSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top">
    92. <Label x:Name="sTermin"
    93. FontSize="20"
    94. HorizontalContentAlignment="Left"
    95. VerticalContentAlignment="Top"
    96. Content="{Binding Termin}">
    97. </Label>
    98. </Viewbox>
    99. <Viewbox x:Name="vbWoche"
    100. Grid.Row="0"
    101. Grid.Column="3"
    102. Panel.ZIndex="1">
    103. <Label x:Name="sWoche"
    104. FontSize="8"
    105. HorizontalContentAlignment="Center"
    106. VerticalContentAlignment="Center"
    107. Content="{Binding Woche}">
    108. </Label>
    109. </Viewbox>
    110. </Grid>
    111. </Button>
    112. </Grid>
    113. </UserControl>



    KalendertagControl-Model:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Imports System.Runtime.CompilerServices
    3. Imports WPF_Kalender_01.Utils
    4. Namespace ViewModels
    5. Public Class KalendertagModel
    6. Inherits PropertyChangedBase
    7. Private _Datum As String = "01"
    8. Private _Tag As String = "Mo"
    9. Private _Feiertag As String = "Neujahr"
    10. Private _Termin As String = "Party"
    11. Private _Woche As String = "KW1"
    12. Public Property Datum As String
    13. Get
    14. Return _Datum
    15. End Get
    16. Set(value As String)
    17. _Datum = value
    18. NotifyOfPropertyChange(Datum)
    19. End Set
    20. End Property
    21. Public Property Tag As String
    22. Get
    23. Return _Tag
    24. End Get
    25. Set(value As String)
    26. _Tag = value
    27. NotifyOfPropertyChange(Tag)
    28. End Set
    29. End Property
    30. Public Property Feiertag As String
    31. Get
    32. Return _Feiertag
    33. End Get
    34. Set(value As String)
    35. _Feiertag = value
    36. NotifyOfPropertyChange(Feiertag)
    37. End Set
    38. End Property
    39. Public Property Termin As String
    40. Get
    41. Return _Termin
    42. End Get
    43. Set(value As String)
    44. _Termin = value
    45. NotifyOfPropertyChange(Termin)
    46. End Set
    47. End Property
    48. Public Property Woche As String
    49. Get
    50. Return _Woche
    51. End Get
    52. Set(value As String)
    53. _Woche = value
    54. NotifyOfPropertyChange(Woche)
    55. End Set
    56. End Property
    57. Sub New()
    58. End Sub
    59. Sub New(sDatum As String, sTag As String, sFeiertag As String, sTermin As String, sWoche As String)
    60. Datum = sDatum
    61. Tag = sTag
    62. Feiertag = sFeiertag
    63. Termin = sTermin
    64. Woche = sWoche
    65. End Sub
    66. End Class
    67. End Namespace

    Hmm, also ich hab jetzt das UserControl für einen Kalendertag erstellt.

    Nun wollte ich für den Jahreskalender in einem Grid zwölf Spalten darstellen die die Monate repräsentieren.
    Deswegen wollte ich nun ein Monats-View erstellen in dem das Kalendertag-Control für die Tage des Monats aufgelistet sind.

    Wie kann ich denn nun eine Liste von UserControls erstellen die ich dann in der Monatsansicht anzeigen lasse?
    Das MVVM geht ja nur in eine Richtung, also XAML greift über Bindings auf die Daten zu aber des CodeBehind soll ja nicht ins XAML reinspielen..
    Wenn nach dem Renovieren und Neutapezieren des eigenen Codes die eigenen Probleme nicht kleiner, sondern womöglich noch größer geworden sind und einem die MVVM-Doktrin nicht wirklich angenehm ist, kann man eine Anwendung auch komplett ohne diese Dogmatik programmieren, unabhängig davon, wie einfach oder komplex die Logik der Anwendung sein mag – ist leider kein Witz.
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.
    Ich hab jetzt eine

    VB.NET-Quellcode

    1. ObservableCollection(Of KalendertagModel)
    erstellt, bzw. versucht.

    Wenn ich diese nun der "ItemsSource" zuweise hängt sich der Designer auf und beim starten des Projekts bekomme ich eine "System.StackOverflowException" ausgeworfen.

    Ich hab das Projekt mal als .zip angehängt.

    Mit vb.net kenn ich mich ja bissl aus, aber WPF ist für mich Neuland..ich find WPF aber sehr interessant auf Grund des Binding-Verhaltens und der individuellen Gestaltung der Controls!

    Views:
    Kalendertag:
    Spoiler anzeigen

    XML-Quellcode

    1. <UserControl x:Class="KalendertagView"
    2. x:Name="Kalendertag"
    3. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    4. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    7. xmlns:local="clr-namespace:WPF_Kalender_02"
    8. xmlns:vm="clr-namespace:WPF_Kalender_02.ViewModels"
    9. mc:Ignorable="d"
    10. Height="118"
    11. Width="700">
    12. <UserControl.DataContext>
    13. <vm:KalendertagModel/>
    14. </UserControl.DataContext>
    15. <Grid x:Name="ctrlGrid"
    16. Width="{Binding ActualWidth, ElementName=userControl, Mode=OneWay}"
    17. Height="{Binding ActualHeight, ElementName=userControl, Mode=OneWay}">
    18. <Grid.ColumnDefinitions>
    19. <ColumnDefinition />
    20. </Grid.ColumnDefinitions>
    21. <Grid.RowDefinitions>
    22. <RowDefinition/>
    23. </Grid.RowDefinitions>
    24. <Button x:Name="button" Grid.Column="0"
    25. Grid.Row="0"
    26. Background="LightBlue"
    27. HorizontalAlignment="Center"
    28. VerticalAlignment="Center"
    29. Height="{Binding ActualHeight, ElementName=grid, Mode=OneWay}"
    30. Width="{Binding ActualWidth, ElementName=grid, Mode=OneWay}">
    31. <Grid x:Name="btnGrid"
    32. Width="{Binding ActualWidth, ElementName=button, Mode=OneWay}"
    33. Height="{Binding ActualHeight, ElementName=button, Mode=OneWay}"
    34. HorizontalAlignment="Center"
    35. VerticalAlignment="Center">
    36. <Grid.ColumnDefinitions>
    37. <ColumnDefinition x:Name="Col1" Width="100*"/>
    38. <ColumnDefinition x:Name="Col2" Width="100*"/>
    39. <ColumnDefinition x:Name="Col3" Width="200*"/>
    40. <ColumnDefinition x:Name="Col4" Width="30*"/>
    41. </Grid.ColumnDefinitions>
    42. <Grid.RowDefinitions>
    43. <RowDefinition x:Name="Row1" Height="20*"/>
    44. <RowDefinition x:Name="Row2" Height="20*"/>
    45. <RowDefinition x:Name="Row3" Height="20*"/>
    46. <RowDefinition x:Name="Row4" Height="20*"/>
    47. </Grid.RowDefinitions>
    48. <Viewbox x:Name="vbDatum"
    49. Grid.Row="0"
    50. Grid.Column="0"
    51. Grid.RowSpan="4">
    52. <Label x:Name="sDatum"
    53. FontSize="20"
    54. HorizontalContentAlignment="Center"
    55. VerticalContentAlignment="Center"
    56. HorizontalAlignment="Stretch"
    57. VerticalAlignment="Stretch"
    58. Content="{Binding Datum}">
    59. </Label>
    60. </Viewbox>
    61. <Viewbox x:Name="vbTag"
    62. Grid.Row="0"
    63. Grid.Column="1"
    64. Grid.RowSpan="4">
    65. <Label x:Name="sTag"
    66. FontSize="20"
    67. HorizontalContentAlignment="Center"
    68. VerticalContentAlignment="Center"
    69. HorizontalAlignment="Stretch"
    70. VerticalAlignment="Stretch"
    71. Content="{Binding Tag}">
    72. </Label>
    73. </Viewbox>
    74. <Viewbox x:Name="vbFeiertag"
    75. Grid.Row="0"
    76. Grid.Column="2"
    77. Grid.RowSpan="2"
    78. Grid.ColumnSpan="2"
    79. HorizontalAlignment="Left"
    80. VerticalAlignment="Top">
    81. <Label x:Name="sFeiertag"
    82. FontSize="20"
    83. HorizontalContentAlignment="Left"
    84. VerticalContentAlignment="Top"
    85. Content="{Binding Feiertag}">
    86. </Label>
    87. </Viewbox>
    88. <Viewbox x:Name="vbTermin"
    89. Grid.Row="2"
    90. Grid.Column="2"
    91. Grid.RowSpan="2"
    92. Grid.ColumnSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top">
    93. <Label x:Name="sTermin"
    94. FontSize="20"
    95. HorizontalContentAlignment="Left"
    96. VerticalContentAlignment="Top"
    97. Content="{Binding Termin}">
    98. </Label>
    99. </Viewbox>
    100. <Viewbox x:Name="vbWoche"
    101. Grid.Row="0"
    102. Grid.Column="3"
    103. Panel.ZIndex="1">
    104. <Label x:Name="sWoche"
    105. FontSize="8"
    106. HorizontalContentAlignment="Center"
    107. VerticalContentAlignment="Center"
    108. Content="{Binding Woche}">
    109. </Label>
    110. </Viewbox>
    111. </Grid>
    112. </Button>
    113. </Grid>
    114. </UserControl>


    Kalendermonat:
    Spoiler anzeigen

    XML-Quellcode

    1. <UserControl x:Class="KalendermonatView"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    5. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    6. xmlns:local="clr-namespace:WPF_Kalender_02"
    7. xmlns:vm="clr-namespace:WPF_Kalender_02.ViewModels"
    8. mc:Ignorable="d" Height="470" Width="345">
    9. <!--<UserControl.DataContext>
    10. <local:KalendermonatView/>
    11. </UserControl.DataContext>-->
    12. <Grid>
    13. <Grid.ColumnDefinitions>
    14. <ColumnDefinition/>
    15. </Grid.ColumnDefinitions>
    16. <Grid.RowDefinitions>
    17. <RowDefinition Height="Auto"/>
    18. <RowDefinition />
    19. <RowDefinition Height="Auto"/>
    20. </Grid.RowDefinitions>
    21. <Grid.Resources>
    22. <DataTemplate DataType="{x:Type vm:KalendertagModel}">
    23. <local:KalendertagView/>
    24. </DataTemplate>
    25. </Grid.Resources>
    26. <TextBlock Text="Monatstame"
    27. FontWeight="Bold" Margin="4 10"/>
    28. <ListBox ItemsSource="{Binding Kalendertage_Collection}" Margin="4" Grid.Row="1">
    29. <ListBox.ItemContainerStyle>
    30. <Style TargetType="ListBoxItem">
    31. <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    32. </Style>
    33. </ListBox.ItemContainerStyle>
    34. </ListBox>
    35. </Grid>
    36. </UserControl>


    Models:
    Kalendertag:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports WPF_Kalender_02.Utils
    2. Namespace ViewModels
    3. <Serializable()>
    4. Public Class KalendertagModel
    5. Inherits PropertyChangedBase
    6. Private _Datum As String = "01"
    7. Private _Tag As String = "Mo"
    8. Private _Feiertag As String = "Neujahr"
    9. Private _Termin As String = "Party"
    10. Private _Woche As String = "KW1"
    11. Public Property Datum As String
    12. Get
    13. Return _Datum
    14. End Get
    15. Set(value As String)
    16. _Datum = value
    17. NotifyOfPropertyChange(Datum)
    18. End Set
    19. End Property
    20. Public Property Tag As String
    21. Get
    22. Return _Tag
    23. End Get
    24. Set(value As String)
    25. _Tag = value
    26. NotifyOfPropertyChange(Tag)
    27. End Set
    28. End Property
    29. Public Property Feiertag As String
    30. Get
    31. Return _Feiertag
    32. End Get
    33. Set(value As String)
    34. _Feiertag = value
    35. NotifyOfPropertyChange(Feiertag)
    36. End Set
    37. End Property
    38. Public Property Termin As String
    39. Get
    40. Return _Termin
    41. End Get
    42. Set(value As String)
    43. _Termin = value
    44. NotifyOfPropertyChange(Termin)
    45. End Set
    46. End Property
    47. Public Property Woche As String
    48. Get
    49. Return _Woche
    50. End Get
    51. Set(value As String)
    52. _Woche = value
    53. NotifyOfPropertyChange(Woche)
    54. End Set
    55. End Property
    56. End Class
    57. End Namespace




    Kalendermonat-View Class:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Collections.ObjectModel
    2. Imports System.ComponentModel
    3. Imports WPF_Kalender_02.ViewModels
    4. Partial Public Class KalendermonatView
    5. Inherits UserControl
    6. Private _Kalendertage_Collection As New ObservableCollection(Of KalendertagModel)
    7. <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
    8. Public ReadOnly Property Kalendertage_Collection As ObservableCollection(Of KalendertagModel)
    9. Get
    10. Return _Kalendertage_Collection
    11. End Get
    12. End Property
    13. Sub New()
    14. 'CreateCollection(Now)
    15. InitializeComponent()
    16. DataContext = Me
    17. End Sub
    18. Private Sub CreateCollection(d As Date)
    19. Dim newList As New List(Of Date)
    20. If d.YearsMonthsDictionary.TryGetValue(d.NameOfMonth, newList) Then
    21. _Kalendertage_Collection = New ObservableCollection(Of KalendertagModel)
    22. For Each dDate As Date In newList
    23. _Kalendertage_Collection.Add(New KalendertagModel With {
    24. .Datum = dDate.NameOfDay,
    25. .Feiertag = "",
    26. .Tag = dDate.Day.ToString,
    27. .Termin = "",
    28. .Woche = "KW" & dDate.CalendarWeek})
    29. Next
    30. Else
    31. Debug.WriteLine("Fehler beim erstellen der ObservableCollection!")
    32. Exit Sub
    33. End If
    34. End Sub
    35. End Class



    Dateien

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Morrison“ ()

    Im Gegensatz zu Gregor vermute ich die Probleme eher darin, dass hier MVVM nicht richtig angewendet wurde.

    Aber ich weiss grad nicht, in welche Richtung gelaufen wird: Versuchst du, das Problem mit oder gegen MVVM zu lösen?

    Weil bei gegen haltich mich besser zurück - hat ja kein Sinn, mehrere Lösungswege gleichzeitig zu beschreiten, die einander auch noch ausschliessen.

    Morrison schrieb:

    (...) Mit vb.net kenn ich mich ja bissl aus, aber WPF ist für mich Neuland..ich find WPF aber sehr interessant auf Grund des Binding-Verhaltens und der individuellen Gestaltung der Controls! (...)

    Ja, ja, die Bindungen – wo man dann das Gefühl hat, dass quasi alles automatisch läuft oder laufen könnte, ohne dass man dafür die Logik tatsächlich bis ins Detail ausformulieren muss – können einen schon mal ganz schön locken, aber wenn man tatsächlich neu im Geschäft ist, wie man selbst schreibt, ist so ein Kalender – wie man sich ihn vorgestellt hat – möglicherweise etwas zu viel für den Anfang – eine klassische Überforderung. Man kann erstmal kleine Brötchen nach der MVVM-Doktrin backen lernen, am besten nur ein Brötchen ohne alles, und wenn dass klappt, kann man die Liste der Zutaten erweitern, die Öfen und deren Temperaturen vergrößern.
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.

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

    Also ich traue mir schon zu soeinen Kalender zu realisieren, ist halt jetzt nur das Problem das ich den Kalender selbst aus mehreren UserControls zusammenbauen muss, was nun doch recht kompliziert erscheint. (Sprung ins kalte, nasse Wasser)
    Und das MVVM-Prinzip wollte ich schon einhalten. Kann natürlich sein das ich dies mit der Partial Class verletzt hab. Durch mehrere Beispiele aussm Web ist nun halt sowas draus geworden.
    Ich hatte aber kurz den Erfolg das mir die Monatsansicht die TagesControls angezeigt hatte und ich dachte das wärs, aber zwei Klicks später kapitulierte der Designer..mpf
    @Morrison Ich habe eine Mappe angehängt, ein CustomControl mit ResourceDictionary das ein Style mit Template mit ControlTemplate beinhaltet. So kannst du dann das Layout festlegen und weitere Controls in dem Control einbauen.

    Ob man dafür auch MVVM anwenden kann/sollte bin ich mir noch nicht sicher, brauch noch ein bisschen um damit richtig klar zu kommen, da frage ich hier mal ganz frech @ErfinderDesRades. Wie würdest du Costum-Controls(nicht User-Controls) in WPF machen?

    Ich habe einfach mal diverse Sachen ausprobiert, bin zig mal auf die Nase gefallen. Aber nun hab ich was, was schon mal funktioniert. Das ist nur zu Trainingszwecken, Das Control hat 2 Labels und 2 Buttons, Buttons für je Tag vor und Tag zurück, die beiden Labels zeigen das Datum in 2 verschiedenen Formaten an. Die Observable klasse spar ich mal aus, die implementiert nur INotifyPropertyChanged.
    CalendarDay.cs
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Diagnostics;
    4. using System.Globalization;
    5. using System.Linq;
    6. using System.Text;
    7. using System.Threading.Tasks;
    8. using System.Windows;
    9. using System.Windows.Controls;
    10. using System.Windows.Media;
    11. using System.Windows.Threading;
    12. namespace CalendarTest
    13. {
    14. public partial class CalendarDay : Control
    15. {
    16. public static DependencyProperty DateProperty = DependencyProperty.Register("Date1", typeof(DateTime), typeof(CalendarDay), new PropertyMetadata(new DateTime(), new PropertyChangedCallback(DateChanged)));
    17. Label lblDateDetail;
    18. Label lblDate;
    19. Button btnPrevious;
    20. Button btnNext;
    21. private static void DateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    22. {
    23. DateTime dt = (DateTime)d.GetValue(DateProperty);
    24. CalendarDay calendarDay = (CalendarDay)d;
    25. if(calendarDay.lblDate != null) calendarDay.lblDate.Content = dt.ToString("d", CultureInfo.CurrentCulture);
    26. if(calendarDay.lblDateDetail != null) calendarDay.lblDateDetail.Content = dt.ToString("D", CultureInfo.CurrentCulture);
    27. }
    28. public static void SetDate1(UIElement uIElement, DateTime dt)
    29. {
    30. uIElement.SetValue(DateProperty, dt);
    31. }
    32. public static DateTime GetDate1(UIElement uIElement)
    33. {
    34. return (DateTime)uIElement.GetValue(DateProperty);
    35. }
    36. static CalendarDay()
    37. {
    38. DefaultStyleKeyProperty.OverrideMetadata(typeof(CalendarDay), new FrameworkPropertyMetadata(typeof(CalendarDay)));
    39. if(!Application.Current.Resources.Contains("CalendarDaySytle"))
    40. {
    41. Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("pack://application:,,,/CalendarTest;component/CalendarDay.xaml", UriKind.Absolute) });
    42. }
    43. }
    44. public override void OnApplyTemplate()
    45. {
    46. base.OnApplyTemplate();
    47. lblDate = GetTemplateChild("lbl_date") as Label;
    48. lblDateDetail = GetTemplateChild("lbl_date_detail") as Label;
    49. btnNext = GetTemplateChild("btn_next") as Button;
    50. btnNext.Click += btnNext_Click;
    51. btnPrevious = GetTemplateChild("btn_prev") as Button;
    52. btnPrevious.Click += btnPrevious_Click;
    53. lblDate.Content = GetDate1(this).ToString("d", CultureInfo.CurrentCulture);
    54. lblDateDetail.Content = GetDate1(this).ToString("D", CultureInfo.CurrentCulture);
    55. }
    56. private void btnNext_Click(object sender, RoutedEventArgs e)
    57. {
    58. DateTime d = (DateTime)GetDate1(this);
    59. try {
    60. d = d.AddDays(1);
    61. SetDate1(this, d);
    62. }
    63. catch (OverflowException ex) { Debug.Write(ex.Message); }
    64. }
    65. private void btnPrevious_Click(object sender, RoutedEventArgs e)
    66. {
    67. DateTime d = (DateTime)GetDate1(this);
    68. try
    69. {
    70. d = d.AddDays(-1);
    71. SetDate1(this, d);
    72. }
    73. catch (OverflowException ex) { Debug.Write(ex.Message); }
    74. }
    75. }
    76. }

    CalendarDay.xaml
    Spoiler anzeigen

    XML-Quellcode

    1. <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    2. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    3. xmlns:local="clr-namespace:CalendarTest"
    4. x:Name="CalendarDayStyle">
    5. <Style TargetType="{x:Type local:CalendarDay}">
    6. <Setter Property="Template">
    7. <Setter.Value>
    8. <ControlTemplate TargetType="{x:Type local:CalendarDay}">
    9. <Grid Height="80">
    10. <Grid.RowDefinitions>
    11. <RowDefinition Height="30"/>
    12. <RowDefinition Height="30"/>
    13. </Grid.RowDefinitions>
    14. <Grid.ColumnDefinitions>
    15. <ColumnDefinition Width="80"/>
    16. <ColumnDefinition Width="*"/>
    17. <ColumnDefinition Width="80"/>
    18. </Grid.ColumnDefinitions>
    19. <Label Grid.Row="0" Grid.ColumnSpan="3" x:Name="lbl_date" Content="1.1.2000" HorizontalContentAlignment="Center"/>
    20. <Button Grid.Row="1" x:Name="btn_prev" Content="&lt;"/>
    21. <Label Grid.Row="1" Grid.Column="1" x:Name="lbl_date_detail" Content="1" HorizontalContentAlignment="Center"/>
    22. <Button Grid.Row="1" Grid.Column="2" x:Name="btn_next" Content="&gt;"/>
    23. </Grid>
    24. </ControlTemplate>
    25. </Setter.Value>
    26. </Setter>
    27. </Style>
    28. </ResourceDictionary>


    Ab hier dann MVVM Pattern bei der Anwendung des Controls:
    MainWIndow.xaml
    Spoiler anzeigen

    XML-Quellcode

    1. <Window x:Class="CalendarTest.MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:local="clr-namespace:CalendarTest"
    7. mc:Ignorable="d"
    8. Title="MainWindow" Height="450" Width="800">
    9. <Window.DataContext>
    10. <local:MainWindowViewModel/>
    11. </Window.DataContext>
    12. <Grid>
    13. <local:CalendarDay Date1="{Binding TheDate}" Width="400" Height="100"/>
    14. </Grid>
    15. </Window>

    Und noch das ViewModel:
    Spoiler anzeigen

    C#-Quellcode

    1. public class MainWindowViewModel : Observable
    2. {
    3. private DateTime theDate = new DateTime();
    4. public DateTime TheDate { get => theDate; set { theDate = value; RaisePropertyChanged(nameof(TheDate)); } }
    5. public MainWindowViewModel()
    6. {
    7. TheDate = DateTime.Now;
    8. }
    9. }

    Bilder
    • Unbenannt.png

      11,47 kB, 1.031×585, 38 mal angesehen
    Dateien
    • CalendarTest.zip

      (6,68 kB, 44 mal heruntergeladen, zuletzt: )
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „DTF“ ()

    Morrison schrieb:

    (...) Und das MVVM-Prinzip wollte ich schon einhalten (...)

    Wer an die MVVM-Doktrin glaubt, sollte bereit sein, zu leiden und sich vor allem nach den Regeln dieser Glaubensansätze ausrichten, egal wie sinnvoll oder weniger sinnvoll sie sein mögen, sonst gibt es gleich einen Aufschrei der Pharisäer, die ihren Jüngern diese Lehre um jeden Preis so eintrichtern wollen, wie sie im Kanon ins Stein gemeißelt worden ist ; ) Aber Spaß beiseite, wie ich schon sagte, ich persönlich würde mich der Sache langsam annähern, erstmal ein Brötchen ohne alles (also nix gleich mit saftigem Schinken oder so) in einem kleinen Backofen kreieren, um dann mit Analogien und weiteren, neuen Elementen aus dem MVVM-Pool das ganze zu erweitern oder nur üben und dadurch verstehen lernen, um danach das Eigentliche als ein neues Projekt auf die Beine stellen, denn wenn man es umgekehrt macht, wird man stolpern – solche Enttäuschungen können dann dazu führen, das man WPF ganz schmeißt, was schade wäre, denn man kann da auch sehr schön ohne diese ganze MVVM-Dogmatik programmieren – WPF ist für alle da. Wenn man den Code von jemandem quasi fertig bekommt, wird das einem in so einer Situation nur kurzfristig, aber nicht dauerhaft helfen, weil eben die Nachhaltigkeit fehlt; aber wie gesagt, ist nur meine persönliche Meinung – jeder darf das tun, was er für richtig hält, das gilt auch für die Art und Weise wie man z.B. in WPF, WinForms oder sonst wo programmiert. Wenn man wirklich programmieren kann, wird man das nach einer gewissenhaften Einarbeitung in die Materie auch überall können, sofern man bereit ist, etwas dafür zu tun, denn umsonst gibt es eigentlich nichts bei solchen Dingen, mogeln geht hier leider (oder zum Glück) nicht, man muss was dafür tun, in der Regel viele Jahre Wissen und Erfahrung sammeln.
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.

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

    @Gregor Jasinski
    Ich muss gestehen, ich liebe MVVM. Am Anfang war es ungewohnt und ein wenig tricky, da hatte ich ein wenig gelitten. Ich arbeite voll MVVM konform(In Anwendungen, Control-Klassenbibliotheken nicht), also kein CodeBehind in Anwendungen, wäre aber im Zweifel bereit für ein paar Zeilen CodeBehind. Bisher kam ich ohne CodeBehind aus, abgesehen von CustomControls. Da hab ich dann Klasse(n) + ResourceDictionary. Aber ganz ehrlich, bei Custom-Controls habe ich mehr gelitten als beim lernen, verstehen und anwenden des MVVM-Patterns.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    Also ich hab jetzt alles aus dem CodeBehind der Views rausgeschmissen!
    Das erstellen der ObservableCollection hab ich ins ViewModel getan ( ist hoff. MVVM-Konform ) und nun scheint es zu funktionieren!

    KalendermonatView:
    Spoiler anzeigen

    XML-Quellcode

    1. <UserControl x:Class="KalendermonatView"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    5. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    6. xmlns:local="clr-namespace:WPF_Kalender_02"
    7. xmlns:vm="clr-namespace:WPF_Kalender_02.ViewModels"
    8. mc:Ignorable="d"
    9. Height="470"
    10. Width="345">
    11. <UserControl.DataContext>
    12. <vm:KalendermonatModel/>
    13. </UserControl.DataContext>
    14. <Grid>
    15. <Grid.ColumnDefinitions>
    16. <ColumnDefinition/>
    17. </Grid.ColumnDefinitions>
    18. <Grid.RowDefinitions>
    19. <RowDefinition Height="Auto"/>
    20. <RowDefinition />
    21. <RowDefinition Height="Auto"/>
    22. </Grid.RowDefinitions>
    23. <Grid.Resources>
    24. <DataTemplate DataType="{x:Type vm:KalendertagModel}">
    25. <local:KalendertagView/>
    26. </DataTemplate>
    27. </Grid.Resources>
    28. <TextBlock Text="Monatstame"
    29. FontWeight="Bold" Margin="4 10"/>
    30. <ListBox ItemsSource="{Binding Kalendertage_Collection}" Margin="4" Grid.Row="1">
    31. <ListBox.ItemContainerStyle>
    32. <Style TargetType="ListBoxItem">
    33. <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    34. </Style>
    35. </ListBox.ItemContainerStyle>
    36. </ListBox>
    37. </Grid>
    38. </UserControl>


    KalendermonatModel:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Collections.ObjectModel
    2. Imports System.ComponentModel
    3. Imports WPF_Kalender_02.Utils
    4. Namespace ViewModels
    5. Public Class KalendermonatModel
    6. Inherits PropertyChangedBase
    7. Private sMonat As String = "Januar"
    8. Public Property Monat As String
    9. Get
    10. Return sMonat
    11. End Get
    12. Set(value As String)
    13. sMonat = value
    14. NotifyOfPropertyChange()
    15. End Set
    16. End Property
    17. Private _Kalendertage_Collection As New ObservableCollection(Of KalendertagModel)
    18. '<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
    19. Public ReadOnly Property Kalendertage_Collection As ObservableCollection(Of KalendertagModel)
    20. Get
    21. Return _Kalendertage_Collection
    22. End Get
    23. End Property
    24. Private Sub CreateCollection(d As Date)
    25. Dim newList As New List(Of Date)
    26. If d.YearsMonthsDictionary.TryGetValue(d.NameOfMonth, newList) Then
    27. _Kalendertage_Collection = New ObservableCollection(Of KalendertagModel)
    28. For Each dDate As Date In newList
    29. _Kalendertage_Collection.Add(New KalendertagModel With {
    30. .Datum = dDate.NameOfDay,
    31. .Feiertag = "",
    32. .Tag = dDate.Day.ToString,
    33. .Termin = "",
    34. .Woche = "KW" & dDate.CalendarWeek})
    35. ' Kalendertage_Collection.Add(New KalendertagModel())
    36. Next
    37. Else
    38. Debug.WriteLine("Fehler beim erstellen der ObservableCollection!")
    39. Exit Sub
    40. End If
    41. End Sub
    42. Sub New()
    43. CreateCollection(Now)
    44. End Sub
    45. End Class
    46. End Namespace


    Nun bin ich einen großen Schritt weiter! ;)
    Kleine Anmerkung dazu. KalendermonatModel da finde ich den Namen unpassend, weil keine Models sondern ViewModels als DataContext für die Windows festgelegt werden. KalendermonatViewModel würde passen.

    Eine Model Klasse hält die Daten, wie z.B. in Forms eine Zeile vom DataTable

    Kleines einfaches Beispiel, sollte deutlich machen, wofür Models da sind.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class AlbumModel
    2. Public Titles As New List(Of TitleModel)
    3. 'name, albumartist, coverart usw...
    4. End Class
    5. Public Class TitleModel
    6. 'name, titel, artist usw.
    7. End Class
    8. Public Class TheViewMdoel
    9. Inherits Observable 'klasse die InotifyPropertyChange implmentiert
    10. Private _albumModels As ObservableCollection(Of AlbumModel) = New ObservableCollection(Of AlbumModel)
    11. Public Property AlbumModels As ObservableCollection(Of AlbumModel)
    12. Get
    13. Return _albumModels
    14. End Get
    15. Set(value As ObservableCollection(Of AlbumModel))
    16. _albumModels = value
    17. RaisePropertyChanged(NameOf(AlbumModels))
    18. End Set
    19. End Property
    20. End Class

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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