none
WPF - ComboBox group erstellen in MVVM RRS feed

  • Frage

  • Hallo, 

    ich bin gerade am verzweifeln, wie ich meine ComboBox groupen kann.

    Ich hab eine Country-Datenbank, aus der ich die Einträge in die Combobox lade.


    So sieht das aktuell aus:                                     und so will ich es:
    ComboBox                                                         ComboBox
    -Land 1                                                             -Wichtige Länder
    -Land 2                                                                    -Land 1
    -Land 3                                                                    -Land 2
                                                                             -Rest der Länder
                                                                                   -Land 3
                                                                                   -Land 4
                                                                                   -evtl. auch wieder Land 1 und 2

    So sieht das ganze aktuell aus:

    XAML:

            <ComboBox SelectedValue="{Binding SelectedValueNormalLayout, Mode=TwoWay}" ItemsSource="{Binding Countries}" Visibility="{Binding VisibilityNormalLayout, Mode=TwoWay}" FontSize="{Binding fontSize_Content}"></ComboBox>

    ViewModel dazu:

      private List<Country> _countries;
            public List<Country> Countries
            {
                get => _countries;
                set
                {
                    _countries = value;
                    RaisePropertyChanged();
                }
    
            }

     public void GetCountriesComboBox()
            {
                try
                {
                    NamesDB.Open();
                    string NamesCommand = "SELECT * FROM [Country]";
                    OleDbDataAdapter dr = new OleDbDataAdapter(new OleDbCommand(NamesCommand, NamesDB));
                    DataSet ds = new DataSet();
                    dr.Fill(ds);
                    var empList = ds.Tables[0].AsEnumerable().Select(dataRow => new Country { Name = dataRow.Field<string>("NameCountry") }).ToList();
                    Countries = empList;
                    NamesDB.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
     public class Country
                {
                   public string Name { get; set; }
                }

    Danke für die Hilfe
    Micha

                                                        


    • Bearbeitet michad2151 Donnerstag, 29. August 2019 06:11
    Donnerstag, 29. August 2019 06:10

Antworten

  • Hi Micha,
    hier mal eine kleine Demo:

    XAML:

    <Window x:Class="WpfApp1.Window60"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="Window60" Height="450" Width="800">
      <Window.DataContext>
        <local:Window60VM/>
      </Window.DataContext>
        <StackPanel>
        <ComboBox ItemsSource="{Binding View}">
          <ComboBox.ItemTemplate>
            <DataTemplate>
              <StackPanel Orientation="Horizontal">
                <TextBlock x:Name="txt1" Text="- "/>
                <TextBlock x:Name="txt2" Text="    - "/>
                <TextBlock Text="{Binding Land}"/>
              </StackPanel>
              <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Header}"  Value="True">
                  <Setter TargetName="txt1" Property="Visibility" Value="Visible"/>
                  <Setter TargetName="txt2" Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding Header}"  Value="False">
                  <Setter TargetName="txt1" Property="Visibility" Value="Collapsed"/>
                  <Setter TargetName="txt2" Property="Visibility" Value="Visible"/>
                </DataTrigger>
              </DataTemplate.Triggers>
            </DataTemplate>
          </ComboBox.ItemTemplate>
        </ComboBox>
      </StackPanel>
    </Window>

    Dazu der ViewModel:

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Data;
    
    namespace WpfApp1
    {
      public class Window60VM
      {
        public Window60VM()
        {
          col.Add(new Window60Data() { Header = true, Gruppe = "A", Land = "Wichtige Länder" });
          col.Add(new Window60Data() { Header = false, Gruppe = "A", Land = "Land 1" });
          col.Add(new Window60Data() { Header = false, Gruppe = "A", Land = "Land 3" });
          col.Add(new Window60Data() { Header = true, Gruppe = "B", Land = "Rest der Länder" });
          col.Add(new Window60Data() { Header = false, Gruppe = "B", Land = "Land 2" });
          col.Add(new Window60Data() { Header = false, Gruppe = "B", Land = "Land 4" });
          cvs.Source = col;
        }
    
        private CollectionViewSource cvs = new CollectionViewSource();
        private ObservableCollection<Window60Data> col = new ObservableCollection<Window60Data>();
        public ICollectionView View { get { return cvs.View; } }
      }
    
      public class Window60Data
      {
        public bool Header { get; set; }
        public string Gruppe { get; set; }
        public string Land { get; set; }
      }
    }
    


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Donnerstag, 29. August 2019 11:21

Alle Antworten

  • Hi,
    Deine Frage ist etwas unklar.

    Nach welchem Kriterium sollen die Daten gruppiert werden? In Deiner Klasse Country wird nur die Eigenschaft "Name" geladen/beschrieben.

    Wie soll die Combobox aufgeklappt werden? Soll nur "Wichtige Länder" und "Rest der Länder" aufgeklappt werden und dann eine Liste erscheinen?

    Ich würde anstelle einer Combobox dafür ein TreeView Steuerelement nutzen.


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Donnerstag, 29. August 2019 06:56
  • Hi Peter,

    ich würde wollen, dass das Land "Deutschland" und das Land "Schweiz" ganz oben steht. Also einfach nach beliebigem String sortiert.

    Der Rest der Länder soll dann unten zu sehen sein.

    Beides soll direkt aufgeklappt sein bzw. so eine Funktion (das Aufklappen) würde ich erst gar nicht wollen.

    In die TreeView müsste ich mich erst einlesen...

    LG
    Micha


    • Bearbeitet michad2151 Donnerstag, 29. August 2019 07:29 rechtschreibung
    Donnerstag, 29. August 2019 07:28
  • Hi,
    wenn es immer aufgeklappt sein soll, dann ist die Combobox bestimmt die falsche Wahl. Eine ListBox wäre das angebracht, ggf. mit unterschiedlichem Template bzw. TemplateSelector für die Gruppierungsbezeichnung und die einzelnen Datenobjekte. Es bleibt aber immer noch die Frage, nach welchem Kriterium gruppiert werden soll.

    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Donnerstag, 29. August 2019 07:37
  • Hi,

    okay vielleicht war das ein bisschen von mir missverstanden..

    Es soll natürlich nicht immer aufgeklappt sein: Erst beim öffnen soll alles zu sehen sein -> also innerhalb der ComboBox soll alles offen sein, die ComboBox an sich natürlich nicht...

    Am besten wäre es, wenn ich eine beliebige Anzahl von Variablen hätte, in denen ich jeweils "Deutschland" "Schweiz" "Frankreich" usw. reinschreiben könnte, und diese dann unter "Wichtige Länder" ganz oben in der ComboBox zu sehen sind. Und nach den Variablen wird dann Gruppiert bzw. diese Länder werden dann oben in der Liste angezeigt

    LG
    Micha
    Donnerstag, 29. August 2019 07:42
  • Hi Micha,
    hier mal eine kleine Demo:

    XAML:

    <Window x:Class="WpfApp1.Window60"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="Window60" Height="450" Width="800">
      <Window.DataContext>
        <local:Window60VM/>
      </Window.DataContext>
        <StackPanel>
        <ComboBox ItemsSource="{Binding View}">
          <ComboBox.ItemTemplate>
            <DataTemplate>
              <StackPanel Orientation="Horizontal">
                <TextBlock x:Name="txt1" Text="- "/>
                <TextBlock x:Name="txt2" Text="    - "/>
                <TextBlock Text="{Binding Land}"/>
              </StackPanel>
              <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Header}"  Value="True">
                  <Setter TargetName="txt1" Property="Visibility" Value="Visible"/>
                  <Setter TargetName="txt2" Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding Header}"  Value="False">
                  <Setter TargetName="txt1" Property="Visibility" Value="Collapsed"/>
                  <Setter TargetName="txt2" Property="Visibility" Value="Visible"/>
                </DataTrigger>
              </DataTemplate.Triggers>
            </DataTemplate>
          </ComboBox.ItemTemplate>
        </ComboBox>
      </StackPanel>
    </Window>

    Dazu der ViewModel:

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Data;
    
    namespace WpfApp1
    {
      public class Window60VM
      {
        public Window60VM()
        {
          col.Add(new Window60Data() { Header = true, Gruppe = "A", Land = "Wichtige Länder" });
          col.Add(new Window60Data() { Header = false, Gruppe = "A", Land = "Land 1" });
          col.Add(new Window60Data() { Header = false, Gruppe = "A", Land = "Land 3" });
          col.Add(new Window60Data() { Header = true, Gruppe = "B", Land = "Rest der Länder" });
          col.Add(new Window60Data() { Header = false, Gruppe = "B", Land = "Land 2" });
          col.Add(new Window60Data() { Header = false, Gruppe = "B", Land = "Land 4" });
          cvs.Source = col;
        }
    
        private CollectionViewSource cvs = new CollectionViewSource();
        private ObservableCollection<Window60Data> col = new ObservableCollection<Window60Data>();
        public ICollectionView View { get { return cvs.View; } }
      }
    
      public class Window60Data
      {
        public bool Header { get; set; }
        public string Gruppe { get; set; }
        public string Land { get; set; }
      }
    }
    


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Donnerstag, 29. August 2019 11:21