Umschaltung zwischen DataTemplates

  • WPF

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von florian03.

    Umschaltung zwischen DataTemplates

    Hallo,

    nachdem nun die Frage nach den Settings geklärt wurde und ich Benutzereinstellungen speichern kann, würde ich diese gerne sinnfoll anwenden.
    Ich habe in meinem Projekt eine Listbox, die mit einem DataTemplate "bestückt" ist:

    XML-Quellcode

    1. ​<ListBox Grid.Row="1" Margin="0,10,0,0" ItemsSource="{Binding AllSnippetsView}" SelectedItem="{Binding SelectedSnippet}">
    2. <ListBox.GroupStyle>
    3. <GroupStyle>
    4. <GroupStyle.ContainerStyle>
    5. <Style TargetType="{x:Type GroupItem}">
    6. <Setter Property="Margin" Value="0,0,0,5"/>
    7. <Setter Property="Template">
    8. <Setter.Value>
    9. <ControlTemplate TargetType="{x:Type GroupItem}">
    10. <Expander IsExpanded="True"
    11. BorderThickness="1,1,1,5">
    12. <Expander.Header>
    13. <DockPanel Margin="0,0,10,0">
    14. <TextBlock FontSize="15" FontWeight="Bold"
    15. Text="{Binding Name.Name}"
    16. Margin="5,0,20,0"
    17. />
    18. <TextBlock FontSize="15" HorizontalAlignment="Right" FontWeight="Bold"
    19. Text="{Binding Path=ItemCount}"/>
    20. </DockPanel>
    21. </Expander.Header>
    22. <Expander.Content>
    23. <ItemsPresenter Margin="0,6,0,0"/>
    24. </Expander.Content>
    25. </Expander>
    26. </ControlTemplate>
    27. </Setter.Value>
    28. </Setter>
    29. </Style>
    30. </GroupStyle.ContainerStyle>
    31. </GroupStyle>
    32. </ListBox.GroupStyle>
    33. <ListBox.ItemTemplate>
    34. <DataTemplate>
    35. <StackPanel Grid.Column="1" Margin="5">
    36. <TextBlock FontSize="14" FontWeight="Bold" Text="{Binding Path=Name}" />
    37. <StackPanel Orientation="Horizontal">
    38. <TextBlock FontSize="13" >
    39. <Run FontWeight="DemiBold" Text="Tags: "/>
    40. <Run Text="{Binding Tags, Mode=OneWay}"/>
    41. </TextBlock>
    42. </StackPanel>
    43. </StackPanel>
    44. </DataTemplate>
    45. </ListBox.ItemTemplate>
    46. <ListBox.ContextMenu>
    47. <ContextMenu>
    48. <MenuItem Icon="{StaticResource EditSnippet}" Command="{Binding EditSnippetCommand}" Header="Bearbeiten"></MenuItem>
    49. <MenuItem Icon="{StaticResource Delete}" Header="Löschen" Command="{Binding DeleteSnippetCommand}"></MenuItem>
    50. </ContextMenu>
    51. </ListBox.ContextMenu>
    52. </ListBox>


    Jetzt möchte ich dem Benutzer in den Settings die Wahl geben, wie die Elemente in der Listbox dargestellt werden.
    Ich habe auch schon ein Zweites DataTemplate erstellt. Dies möchte ich anzeigen wenn ein Property im ViewModel "true" ist.

    Ich wollte es mit DataTemplates umsetzen, habe es aber leider nicht hinbekommen.
    Die Lösung wird wieder relativ einfach sein - ich komme aber einfach nicht drauf ;(

    Wenn jemand einen Denkanstoß hätte, würde ich mich sehr freuen.

    Viele Grüße
    Florian
    ----

    WebApps mit C#: Blazor
    Hallo

    florian03 schrieb:

    Dies möchte ich anzeigen wenn ein Property im ViewModel "true" ist.

    Das musst du bitte genauer Definieren. Möchtest du ein anderes DataTemplate verwenden wenn der Wert "True" ist oder willst du ein anderes Template benutzen wenn der Datentyp Boolean ist.

    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. ##

    Hallo,

    wieder Mal zu ungenau beschrieben... - sorry!

    Also ich habe eine Listbox, in der Objekte (in meinem Fall CodeSnippets) angezeigt werden.
    In meinem Standard Datatemplate verbraucht ein Objekt in der Listbox relativ viel Platz - deswegen habe ich in den Settings einen Boolean Wert hinzugefügt ("UseSmallDatatemplate")
    Dieses Setting ist als Property in meinem ViewModel hinterlegt. Wenn das Property den Wert 'true' hat, dann soll das Datatemplate für die schmale Darstellung der Snippets verwendet werden - bei 'false' das ganz mormale Datatemplate.

    Ich denke das war jetzt verständlich
    Viele Grüße
    Florian
    ----

    WebApps mit C#: Blazor
    Achso.

    Na das geht einfach indem du mittels Trigger den Content umschaltest.

    Du machst also in dein DataTempplate ein ContentControl und setzt mittels Trigger den Content je nach Wert.

    Schau mal hier: stackoverflow.com/questions/71…witching-based-on-trigger

    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. ##

    Hallo, erstmal vielen Dank für deine Antwort.

    Habe es mal versucht umzusetzten, hat auch so weit geklappt mit den Resourcen und DataTemplates, allerdings funktioniert nun mein Binding nicht mehr.
    Die Properties an die ich binde "werden anscheinend nicht gefunden".

    Ich habe mal den Code von dem Listview hier (in gekürzter Form):

    XML-Quellcode

    1. <ListBox Grid.Row="1" Margin="0,10,0,0" ItemsSource="{Binding AllSnippetsView}" SelectedItem="{Binding SelectedSnippet}">
    2. <ListBox.GroupStyle>
    3. <GroupStyle>
    4. <GroupStyle.ContainerStyle>
    5. <Style TargetType="{x:Type GroupItem}">
    6. <Setter Property="Margin" Value="0,0,0,5"/>
    7. <Setter Property="Template">
    8. <Setter.Value>
    9. <ControlTemplate TargetType="{x:Type GroupItem}">
    10. <Expander IsExpanded="True"
    11. BorderThickness="1,1,1,5">
    12. <Expander.Header>
    13. <DockPanel Margin="0,0,10,0">
    14. <TextBlock FontSize="15" FontWeight="Bold"
    15. Text="{Binding Name.Name}"
    16. Margin="5,0,20,0"
    17. />
    18. <TextBlock FontSize="15" HorizontalAlignment="Right" FontWeight="Bold"
    19. Text="{Binding Path=ItemCount}"/>
    20. </DockPanel>
    21. </Expander.Header>
    22. <Expander.Content>
    23. <ItemsPresenter Margin="0,6,0,0"/>
    24. </Expander.Content>
    25. </Expander>
    26. </ControlTemplate>
    27. </Setter.Value>
    28. </Setter>
    29. </Style>
    30. </GroupStyle.ContainerStyle>
    31. </GroupStyle>
    32. </ListBox.GroupStyle>
    33. <ListBox.ItemTemplate>
    34. <DataTemplate>
    35. <ContentControl DataContext="{Binding Mode=OneWay}">
    36. <ContentControl.Resources>
    37. <DataTemplate x:Key="normalListView">
    38. <StackPanel Grid.Column="1" Margin="5">
    39. <TextBlock FontSize="14" FontWeight="Bold" Text="{Binding Path=Name}" />
    40. <StackPanel Orientation="Horizontal">
    41. <TextBlock FontSize="13" >
    42. <Run FontWeight="DemiBold" Text="Tags: "/>
    43. <Run Text="{Binding Tags, Mode=OneWay}"/>
    44. </TextBlock>
    45. </StackPanel>
    46. </StackPanel>
    47. </DataTemplate>
    48. <DataTemplate x:Key="slimListView">
    49. <TextBlock Margin="5" FontSize="14" FontWeight="Bold" Text="{Binding Path=Name}" />
    50. </DataTemplate>
    51. </ContentControl.Resources>
    52. <ContentControl.Style>
    53. <Style TargetType="{x:Type ContentControl}">
    54. <Setter Value="{StaticResource normalListView}" Property="ContentTemplate" />
    55. <Style.Triggers>
    56. <DataTrigger Binding="{Binding }" Value="True">
    57. <Setter Value="{StaticResource slimListView}" Property="ContentTemplate" />
    58. </DataTrigger>
    59. </Style.Triggers>
    60. </Style>
    61. </ContentControl.Style>
    62. </ContentControl>
    63. </DataTemplate>
    64. <!--<DataTemplate>
    65. <StackPanel Grid.Column="1" Margin="5">
    66. <TextBlock FontSize="14" FontWeight="Bold" Text="{Binding Path=Name}" />
    67. <StackPanel Orientation="Horizontal">
    68. <TextBlock FontSize="13" >
    69. <Run FontWeight="DemiBold" Text="Tags: "/>
    70. <Run Text="{Binding Tags, Mode=OneWay}"/>
    71. </TextBlock>
    72. </StackPanel>
    73. </StackPanel>
    74. </DataTemplate>-->
    75. </ListBox.ItemTemplate>
    76. </ListBox>

    (Der auskommentierte Abschnitt ist das ursprüngliche DataTemplate, wo das Binding super funktioniert hat.)

    Hier auch mal der Code des ViewModels:
    Spoiler anzeigen

    C#-Quellcode

    1. ​using Microsoft.Win32;
    2. using SnippetLibrary.Context;
    3. using SnippetLibrary.Model;
    4. using SnippetLibrary.View.DialogViews;
    5. using SnippetLibrary.ViewModel.DialogViewModels.SpecialDialogs;
    6. using SnippetLibrary.ViewModel.Infrastructure;
    7. using SnippetLibrary.ViewModel.ModelViewModels;
    8. using System;
    9. using System.Collections.Generic;
    10. using System.Collections.ObjectModel;
    11. using System.ComponentModel;
    12. using System.IO;
    13. using System.Linq;
    14. using System.Text;
    15. using System.Threading.Tasks;
    16. using System.Windows;
    17. using System.Windows.Data;
    18. using System.Windows.Input;
    19. namespace SnippetLibrary.ViewModel.WorkspaceViewModels
    20. {
    21. public class MainWorkspaceViewModel : ViewModelBase
    22. {
    23. public MainWorkspaceViewModel()
    24. {
    25. if (IsInDesignMode)
    26. {
    27. //CreateExampleDatas!!!
    28. }
    29. else
    30. {
    31. AllSnippets = new ObservableCollection<SnippetViewModel>();
    32. }
    33. Init();
    34. }
    35. private void Init()
    36. {
    37. SelectedSnippet = AllSnippets.FirstOrDefault();
    38. AllSnippetsView = CollectionViewSource.GetDefaultView(AllSnippets);
    39. AllSnippetsView.Filter = AllSnippetsView_Filter;
    40. AllSnippetsView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
    41. AllSnippetsView.GroupDescriptions.Add(new PropertyGroupDescription("Language"));
    42. }
    43. #region Snippet, SelectedSnippet, View
    44. //Snippet, SelectedSnippet, View
    45. private ObservableCollection<SnippetViewModel> _AllSnippets;
    46. public ObservableCollection<SnippetViewModel> AllSnippets
    47. {
    48. get { return _AllSnippets; }
    49. set { _AllSnippets = value; RaisePropertyChanged(); }
    50. }
    51. private SnippetViewModel _SelectedSnippet;
    52. public SnippetViewModel SelectedSnippet
    53. {
    54. get { return _SelectedSnippet; }
    55. set { _SelectedSnippet = value; RaisePropertyChanged(); }
    56. }
    57. private ICollectionView _AllSnippetsView;
    58. public ICollectionView AllSnippetsView
    59. {
    60. get { return _AllSnippetsView; }
    61. set { _AllSnippetsView = value; RaisePropertyChanged(); }
    62. }
    63. #endregion
    64. #region Filterlogic
    65. //Filterlogic
    66. private string _FilterText;
    67. public string FilterText
    68. {
    69. get
    70. {
    71. return _FilterText;
    72. }
    73. set
    74. {
    75. _FilterText = value; AllSnippetsView.Refresh(); RaisePropertyChanged();
    76. }
    77. }
    78. private bool AllSnippetsView_Filter(object obj)
    79. {
    80. if (String.IsNullOrEmpty(FilterText)) return true;
    81. SnippetViewModel currentSnippet = (SnippetViewModel)obj;
    82. string lowerFilterText = FilterText.ToLower();
    83. if (currentSnippet.Name.ToLower().Contains(lowerFilterText)) return true;
    84. if (currentSnippet.Language.Name.ToLower().Contains(lowerFilterText)) return true;
    85. if (currentSnippet.Tags.ToLower().Contains(lowerFilterText)) return true;
    86. return false;
    87. }
    88. #endregion
    89. #region Other
    90. //Other
    91. private bool _IsFileOpen;
    92. public bool IsFileOpen
    93. {
    94. get { return _IsFileOpen; }
    95. set { _IsFileOpen = value; RaisePropertyChanged(); }
    96. }
    97. private string _OpenFileName;
    98. public string OpenFileName
    99. {
    100. get { return _OpenFileName; }
    101. set { _OpenFileName = value; RaisePropertyChanged(); RaisePropertyChanged("WindowTitle"); }
    102. }
    103. public string WindowTitle
    104. {
    105. get
    106. {
    107. string s = "SnippetLibrary";
    108. if (IsFileOpen)
    109. {
    110. s += " - " + new FileInfo(OpenFileName).Name;
    111. }
    112. else
    113. {
    114. s += " - keine Datei geöffnet";
    115. }
    116. return s;
    117. }
    118. }
    119. #endregion
    120. //Settings
    121. public bool S_UImainWorkspace_SimpleListBoxStyle
    122. {
    123. get { return false; } //Boolean.Parse( SettingsContext.Instance.GetSettingValue("UImainWorkspace_SimpleListBoxStyle"))
    124. }
    125. }
    126. }



    Das ganze Projekt kann auch gerne auf GitHub angesehen werden: https://github.com/florian03-1/SnippetLibrary

    Viele Grüße
    Florian
    ----

    WebApps mit C#: Blazor
    Davon hab ich noch nichts gehört - was nartürlich nichts heißen muss :)
    Nach einer kurzen Internetrescherche habe ich allerdings nichts nützliches für mich gelesen.

    Die Lösung, die in Post 5 gepostet habe funktioniert auch soweit - also man kann zwichen den beiden Templates umschalten.
    Allerdings funktioniert hier das Binding nicht mehr - sprich es wird z.B. das Property ​Name nicht mehr angezeigt.

    Wenn da jemand einen Tipp hat was ich übersehe...

    Viele Grüße
    Florian
    ----

    WebApps mit C#: Blazor

    florian03 schrieb:

    Allerdings funktioniert hier das Binding nicht mehr

    Da spiele ich gerne "Erzieher" und frage mal: Was sagt die Ausgabe bezüglich Binding Errors??

    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. ##