Laden...

DataGridComboBoxColumn Inhalt gefiltert abhänig von einer Column davor

Erstellt von Pseudonym4711 vor 6 Jahren Letzter Beitrag vor 6 Jahren 1.269 Views
P
Pseudonym4711 Themenstarter:in
55 Beiträge seit 2014
vor 6 Jahren
DataGridComboBoxColumn Inhalt gefiltert abhänig von einer Column davor

Hallo Zusammen,

Ich habe den Code jetzt noch mal komplett überarbeitet, damit vielleicht eine etwas verständlichere Variante daraus geworden ist.

Es gibt 3 Objekte in meiner Testanwendung (Beispielhaft siehe Code).


public class Vorname : ViewModelBase
{
    int _vornameId;
    public int VornameId { get { return _vornameId; } set { _vornameId = value; OnPropertyChanged(); } }

    string _name;
    public string Name { get { return _name; } set { _name = value; OnPropertyChanged(); } }
}


public class Nachname : ViewModelBase
{
    int _nachnameId;
    public int NachnameId { get { return _nachnameId; } set { _nachnameId = value; OnPropertyChanged(); } }

    int _vorname_vornameId;
    public int Vorname_VornameId { get { return _vorname_vornameId; } set { _vorname_vornameId = value; OnPropertyChanged(); } }

    string _name;
    public string Name { get { return _name; } set { _name = value; OnPropertyChanged(); } }
}


public class Namensbewertung : ViewModelBase
{
    int _namensbewertungId;
    public int NamensbewertungId { get { return _namensbewertungId; } set { _namensbewertungId = value; OnPropertyChanged(); } }

    int _vorname_VornameId;
    public int Vorname_VornameId { get { return _vorname_VornameId; } set { _vorname_VornameId = value; OnPropertyChanged(); } }

    int _nachname_NachnameId;
    public int Nachname_NachnameId { get { return _nachname_NachnameId; } set { _nachname_NachnameId = value; OnPropertyChanged(); } }

    string _bewertung;
    public string Bewertung { get { return _bewertung; } set { _bewertung = value; OnPropertyChanged(); } }
}

Im ViewModel erstell ich ein paar Testdaten


public TestViewModel()
{
    base.DisplayName = Strings.MainWindowViewModel_Command_ViewTest;

    Vornamen = new ObservableCollection<Vorname>(
        new List<Vorname>()
            {
                new Vorname { VornameId = 1, Name = "Hans" },
                new Vorname { VornameId = 2, Name = "Klaus" },
                new Vorname { VornameId = 3, Name = "Berta" }
            });

    Nachnamen = new ObservableCollection<Nachname>(
        new List<Nachname>()
            {
                new Nachname { NachnameId = 1, Vorname_VornameId = 1, Name = "Müller" },
                new Nachname { NachnameId = 2, Vorname_VornameId = 1, Name = "Schmidt" },
                new Nachname { NachnameId = 3, Vorname_VornameId = 1, Name = "Schulze" },
                new Nachname { NachnameId = 4, Vorname_VornameId = 2, Name = "Eder" },
                new Nachname { NachnameId = 5, Vorname_VornameId = 2, Name = "Meier" },
                new Nachname { NachnameId = 6, Vorname_VornameId = 2, Name = "Merkel" },
                new Nachname { NachnameId = 7, Vorname_VornameId = 3, Name = "Schröder" },
                new Nachname { NachnameId = 8, Vorname_VornameId = 3, Name = "Gates" },
                new Nachname { NachnameId = 9, Vorname_VornameId = 3, Name = "Schneider" }
            });

    Namensbewertungen = new ObservableCollection<Namensbewertung>(
        new List<Namensbewertung>()
            {
                new Namensbewertung { NamensbewertungId = 1, Vorname_VornameId = 1, Nachname_NachnameId = 1, Bewertung = "Schöner Name"},
                new Namensbewertung { NamensbewertungId = 2, Vorname_VornameId = 1, Nachname_NachnameId = 3, Bewertung = "Wahnsinns Name"},
                new Namensbewertung { NamensbewertungId = 3, Vorname_VornameId = 2, Nachname_NachnameId = 4, Bewertung = "Was für ein Name"},
                new Namensbewertung { NamensbewertungId = 4, Vorname_VornameId = 2, Nachname_NachnameId = 5, Bewertung = "WTF!!!"},
                new Namensbewertung { NamensbewertungId = 5, Vorname_VornameId = 3, Nachname_NachnameId = 8, Bewertung = "Ist das ein Name"},
                new Namensbewertung { NamensbewertungId = 6, Vorname_VornameId = 3, Nachname_NachnameId = 9, Bewertung = "Wer heißt denn bitte so?"}
            });
}

Das Ganze wird dann folgendermaßen in der View an ein DataGird angebunden.


<UserControl x:Class="MVVMTestProjekt.Views.TestView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:vm="clr-namespace:MVVMTestProjekt.ViewModels"
             mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="600"
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             d:DataContext="{d:DesignInstance {x:Type vm:TestViewModel}}" FontSize="16">
    
    <Grid>

        <DataGrid AutoGenerateColumns="False"
                  CanUserAddRows="False"
                  ItemsSource="{Binding Namensbewertungen, UpdateSourceTrigger=PropertyChanged}">

            <DataGrid.Columns>

                <DataGridTextColumn Header="NamensbewertungId"
                                    Binding="{Binding NamensbewertungId, UpdateSourceTrigger=PropertyChanged}" />

                <DataGridComboBoxColumn Header="Vorname_VornameId"
                                        SelectedValueBinding="{Binding Vorname_VornameId, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                                        SelectedValuePath="VornameId"
                                        DisplayMemberPath="Name">

                    <DataGridComboBoxColumn.ElementStyle>
                        <Style TargetType="ComboBox"
                               BasedOn="{StaticResource {x:Type ComboBox}}">
                            <Setter Property="ItemsSource"
                                    Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, 
                                                Path=DataContext.Vornamen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                        </Style>
                    </DataGridComboBoxColumn.ElementStyle>

                </DataGridComboBoxColumn>

                <DataGridComboBoxColumn Header="Nachname_NachnameId"
                                        SelectedValueBinding="{Binding Nachname_NachnameId, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                                        SelectedValuePath="NachnameId"
                                        DisplayMemberPath="Name">
                    <DataGridComboBoxColumn.ElementStyle>
                        <Style TargetType="ComboBox"
                               BasedOn="{StaticResource {x:Type ComboBox}}">
                            
                            <Setter Property="ItemsSource"
                                    Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},
                                                Path=DataContext.Nachnamen, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
                            
                        </Style>
                        
                    </DataGridComboBoxColumn.ElementStyle>

                </DataGridComboBoxColumn>

                <DataGridTextColumn Header="Bewertung"
                                    Binding="{Binding Bewertung, UpdateSourceTrigger=PropertyChanged}" />

            </DataGrid.Columns>
                
        </DataGrid>
        
    </Grid>
</UserControl>

Die ItemsSource der ersten CoboBox sind die Vornamen.
Die ItemsSource der zweiten Combobox sind die Nachnamen.
Die SelectedItems entsprechen jeweils der in Namensbewertungen gespeicherten "FremdId's" (siehe erstes Bild).

Wenn ich nun die zweite ComboBox aufklappe werden alle Nachnamen aufgelistet (siehe zweites Bild).

Ich möchte aber, dass in der zweiten CombBox nur die Nachnamen angezeigt werden, die zum jeweiligen Vornamen - in der ComboBox davor - gemäß ihrer ID's gehören. So eine Art Filter also (siehe bearbeitetes drittes Bild).

Könntet ihr mir hier Tipps geben, wie ich das realisieren könnte?

Danke und Gruß
Torsten

N
42 Beiträge seit 2015
vor 6 Jahren

Ich würde das mit einer einzigen Collection machen, in der alle Properties drin sind.

Dann würde ich die ItemSource der zweiten ComboBox an das SelectedItem der ersten binden und einen Converter bauen, der die auf dieser Basis die Elemente für die zweite filtert (z.B. per LINQ).

T
461 Beiträge seit 2013
vor 6 Jahren

Oder du erstellst eine 2te Property-Collection in der du lediglich die gefilterten Elemente der aktuellen Auswahl zurückgibts, diese dann halt auf die 2te CB bindest.

Hätte zum ersteren Vorschlag den Vorteil, daß man auch im ViewModell auf diese Infos zugreifen kann.

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄