“Cascade” binding on ObservableCollection, containing other ObservableCollection

后端 未结 1 521
情书的邮戳
情书的邮戳 2021-01-27 10:41

I have a project where I need to display a list of contract (Class Affaire). Each contract has a list of phases (Class Phase). I display each of them in 2 different ListView usi

相关标签:
1条回答
  • 2021-01-27 11:33

    Here is the example, based on your source, that will handle all stuff. a View Models:

    using System.Collections.ObjectModel; using System.ComponentModel;

    namespace WpfApp2 { public class BaseViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string nomPropriete)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(nomPropriete));
        }
    }
    
    public class Contexte : BaseViewModel
    {
        private Affaire _selectedAffaire;
        private Phase _selectedPhase;
        public ObservableCollection<Affaire> ListeDesAffaires { get; set; }
    
        public Affaire SelectedAffaire
        {
            get { return _selectedAffaire; }
            set
            {
                _selectedAffaire = value;
                this.NotifyPropertyChanged("SelectedAffaire");
            }
        }
    
        public Phase SelectedPhase
        {
            get { return _selectedPhase; }
            set
            {
                _selectedPhase = value;
                this.NotifyPropertyChanged("SelectedPhase");
            }
        }
    
        public Contexte()
        {
            ListeDesAffaires = new ObservableCollection<Affaire>
            {
                new Affaire("Affaire1"),
                new Affaire("Affaire2")
            };
        }
    }
    
    public class Affaire : BaseViewModel
    {
        private string nom;
        public string Nom
        {
            get { return this.nom; }
            set
            {
                this.nom = value;
                this.NotifyPropertyChanged("Nom");
            }
        }
    
        public ObservableCollection<Phase> ListPhases { get; set; }
    
        public Affaire(string n)
        {
            nom = n;
            ListPhases = new ObservableCollection<Phase>
            {
                new Phase { NomPhase = nom + "_Phase1" },
                new Phase { NomPhase = nom + "_Phase2" }
            };
        }
    }
    
    public class Phase : BaseViewModel
    {
        private string nomPhase;
        public string NomPhase
        {
            get { return this.nomPhase; }
            set
            {
                this.nomPhase = value;
                this.NotifyPropertyChanged("NomPhase");
            }
        }
    
        public ObservableCollection<Assemblage> ListAssemblages { get; set; }
    }
    
    public class Assemblage : BaseViewModel
    {
        private string nom;
        public string Nom
        {
            get { return this.nom; }
            set
            {
                this.nom = value;
                this.NotifyPropertyChanged("Nom");
            }
        }
    
    }
    

    }

    a MainWindow.xaml:

    <Window x:Class="WpfApp2.MainWindow"
            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:WpfApp2"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Window.DataContext>
            <local:Contexte x:Name="Contexte" d:IsDataSource="True" />
        </Window.DataContext>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>
            <ListBox ItemsSource="{Binding ListeDesAffaires}" DisplayMemberPath="Nom" SelectedItem="{Binding SelectedAffaire}"/>
            <ListBox Grid.Column="1" ItemsSource="{Binding SelectedAffaire.ListPhases}" DisplayMemberPath="NomPhase" />
            <Button Grid.Column="2" VerticalAlignment="Top" Click="FillClick">Fill</Button>
            <ListBox Grid.Column="2" ItemsSource="{Binding SelectedPhase.ListAssemblages}" DisplayMemberPath="Nom" Margin="0,20,0,0"/>
        </Grid>
    </Window>
    

    And some code from your question (MainWindow.xaml.cs):

    using System.Collections.ObjectModel;
    using System.Windows;
    
    namespace WpfApp2
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void FillClick(object sender, RoutedEventArgs e)
            {
                Phase ph = new Phase();
                ph.NomPhase = "SomeId";
                ph.ListAssemblages = new ObservableCollection<Assemblage>()
                {
                    new Assemblage { Nom =  "Assemblage1" },
                    new Assemblage { Nom =  "Assemblage2" }
                };
                Contexte.SelectedPhase = ph;
            }
        }
    }
    

    And here is the result:

    This is basic sample that you can extend. It handles all field modification and Add/Remove objects and displays on screen. There is no additional code in MainWindow.xaml.cs. Please ask questions, if any.

    0 讨论(0)
提交回复
热议问题