"Cascade" 绑定到 ObservableCollection,包含其他 ObservableCollection

"Cascade" binding on ObservableCollection, containing other ObservableCollection

我有一个项目需要显示合同列表 (Class Affaire)。 每个合约都有一个阶段列表(Class 阶段)。 我使用绑定在 2 个不同的 ListView 中显示它们中的每一个。 问题是当我从 ListView 中删除一个阶段时,显示阶段的 ListView 也没有更新,我的 ObjectCollection 也没有更新。

我创建了一个包含两个不同 ObservableCollection 的上下文:

ObservableCollection,其中是Affaire的列表。 ObservableCollection 是所选事件中存在的阶段列表

我的上下文如下:

public class Contexte : INotifyPropertyChanged
    {
        private Affaire selectedAffaire;
        private Phase selectedPhase;
        private Assemblage selectedAssemblage;
        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 Assemblage SelectedAssemblage
        {
            get { return selectedAssemblage; }
            set
            {
                selectedAssemblage = value;
                this.NotifyPropertyChanged("SelectedAssemblage");
            }
        }
        private ObservableCollection<Affaire> listeDesAffaires;
        public ObservableCollection<Affaire> ListeDesAffaires
        {
            get { return listeDesAffaires; }
            set { NotifyPropertyChanged(ref listeDesAffaires, value); }
        }
        /**************************************************/

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string nomPropriete)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(nomPropriete));
        }

        private bool NotifyPropertyChanged<T>(ref T variable, T valeur, [CallerMemberName] string nomPropriete = null)
        {
            if (object.Equals(variable, valeur)) return false;

            variable = valeur;
            NotifyPropertyChanged(nomPropriete);
            return true;
        }

    }

我的Class外遇:

public class Affaire : INotifyPropertyChanged
    {
        public long ID { get; set; }
        private string nom;
        public string Nom
        {
            get { return this.nom; }
            set
            {
                if (this.nom != value)
                {
                    this.nom = value;
                    this.NotifyPropertyChanged("Nom");
                }
            }
        }
        private string code;
        public string Code
        {
            get { return this.code; }
            set
            {
                if (this.code != value)
                {
                    this.code = value;
                    this.NotifyPropertyChanged("Code");
                }
            }
        }
        private string comm;
        public string Comm
        {
            get { return this.comm; }
            set
            {
                if (this.comm != value)
                {
                    this.comm = value;
                    this.NotifyPropertyChanged("Comm");
                }
            }
        }
        private ObservableCollection<Phase> listPhases;
        public ObservableCollection<Phase> ListPhases {
            get { return listPhases; }
            set
            {
                listPhases = value;
                if (PropertyChanged != null)
                {
                    NotifyPropertyChanged("ListPhases");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    ....
    }

我的class阶段:

public class Phase : INotifyPropertyChanged
    {
        private string nomPhase;
        public string NomPhase
        {
            get { return this.nomPhase; }
            set
            {
                if (this.nomPhase != value)
                {
                    this.nomPhase = value;
                    this.NotifyPropertyChanged("NomPhase");
                }
            }
        }
        private int priorite;
        public int Priorite
        {
            get { return this.priorite; }
            set
            {
                if (this.priorite != value)
                {
                    this.priorite = value;
                    this.NotifyPropertyChanged("Priorite");
                }
            }
        }
        private string commPhase;
        public string CommPhase
        {
            get { return this.commPhase; }
            set
            {
                if (this.commPhase != value)
                {
                    this.commPhase = value;
                    this.NotifyPropertyChanged("CommPhase");
                }
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
        public long IdAffaire { get; set; }
        public long ID { get; set; }
        private ObservableCollection<Assemblage> listAssemblages;
        public ObservableCollection<Assemblage> ListAssemblages
        {
            get { return listAssemblages; }
            set
            {
                listAssemblages = value;
                if (PropertyChanged != null)
                {
                    NotifyPropertyChanged("ListAssemblages");
                }
            }
        }
    ...
    }

1) 当我双击合同(在 ListView1 中)时,我在 ListView2 中显示其阶段列表,我执行以下操作:

contexte.SelectedAffaire = (Affaire)ListView1.SelectedItem;
contexte.SelectedAffaire.getListPhases();
afficherListview("2");

2) 当我编辑我的阶段时,所有内容都在我的视图中以及在我的 ObservableCollection 中正确更新

3) 对于 adding/removing 个新阶段,所有问题都已解决。

编辑:

Netstep 给出的示例完美运行,但我仍然遇到问题:

我有第三层"Assembly",这是class"Phase"中的一个ObservableCollection,我用四个ListView导航没问题,但是当我想做点别的:当我 right-click 在 "Phase" 的 header 上时,我想在 Assembly 列表中显示 Affaire 中包含的所有程序集的列表,而不过滤 Phase . 为此,我执行以下操作:我在第 3 级列表视图程序集上,右键单击阶段 header,事件如下:

Phase ph = new Phase();
                ph.IdAffaire = contexte.SelectedAffaire.ID;
                ph.ListAssemblages = new ObservableCollection<Assemblage>(contexte.SelectedAffaire.getListAssemblages(true));
                contexte.SelectedPhase = ph;

我"shit"有点做一个新的空阶段,只是为了在里面放一个ObservableCollection并将ObservableCollection绑定到我的ListView3。 编辑:那部分代码运行良好...我只是刷新了代码中某处的上下文并忘记了它,确保出价有问题...全部解决谢谢

这是一个基于您的来源的示例,它将处理所有内容。 查看模型:

使用System.Collections.ObjectModel; 使用 System.ComponentModel;

命名空间 WpfApp2 { public class BaseViewModel:INotifyPropertyChanged { public 事件 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");
        }
    }

}

}

一个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>

以及您问题中的一些代码 (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;
        }
    }
}

结果如下:

这是您可以扩展的基本示例。它处理所有字段修改和 Add/Remove 对象并显示在屏幕上。 MainWindow.xaml.cs 中没有额外的代码。有问题请提问