【问题标题】:"Cascade" binding on ObservableCollection, containing other ObservableCollectionObservableCollection 上的“级联”绑定,包含其他 ObservableCollection
【发布时间】:2017-12-11 07:43:56
【问题描述】:

我有一个项目需要显示合同列表(类事务)。 每个合同都有一个阶段列表(类阶段)。 我使用绑定在 2 个不同的 ListView 中显示它们中的每一个。 问题是当我从 ListView 中删除一个 Phase 时,也没有更新显示 Phases 的 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;
        }

    }

我的班级事务:

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));
        }
    ....
    }

我的班级阶段:

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) 对于添加/删除新阶段,一切都解决了。

编辑:

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

我有第三级“Assembly”,这是“Phase”类中的 ObservableCollection,我可以使用四个 ListView 进行导航,但是当我想做其他事情时遇到了问题:当我对 -点击“阶段”的标题,我想在Assembly的列表中显示Affaire中包含的所有程序集的列表,而不是在Phase上过滤。 为此,我执行以下操作:我在第 3 级列表视图组件上,我右键单击阶段标题,事件如下:

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

我在创建一个新的空阶段时有点“操蛋”,只是为了将 ObservableCollection 放入其中并将 ObservableCollection 绑定到我的 ListView3。 编辑:那部分代码运行良好...我刚刚刷新了代码中某处的上下文并忘记了它,确定出价有问题...全部解决了谢谢

【问题讨论】:

    标签: c# binding observablecollection


    【解决方案1】:

    这是一个示例,根据您的来源,它将处理所有内容。 视图模型:

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

    命名空间 WpfApp2 { 公共类 BaseViewModel : INotifyPropertyChanged { 公共事件 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;
            }
        }
    }
    

    结果如下:

    这是您可以扩展的基本示例。它处理所有字段修改和添加/删除对象并显示在屏幕上。 MainWindow.xaml.cs 中没有其他代码。如果有问题,请提出问题。

    【讨论】:

    • ohoh... 完美答案谢谢,不知道你可以绑定 SelectedItem,非常感谢 :)。我想要删除/添加阶段,我只需要像 SelectedAffaire.ListeDesPhases.Add(MyPhase) 或 SelectedAffaire.ListeDesPhases.Remove(MyPhase) 那样做一些事情?不再需要 4 个 ObservableCollection,只需要一个,在 ListViewAffaire.SelectedItem 上绑定 ListViewPhase,在 ListViewPhase.SelectedItem 上绑定 ListviewSubPhase 等等……(实际上我不会有 2 个,而是 4 个这样的级别)
    • 对不起,我还是遇到了一个问题,将编辑我的帖子来解释它^^'
    • 我编辑了我的答案并添加了一个执行类似代码的按钮,它可以工作,希望对你有所帮助
    • 可能是您的问题发生了,因为您没有将 ph 添加到列表 ItemssSource 中,它找不到它并覆盖 SelectedItem...
    • 问题不在于填充程序集:假设 Contract1 有两个阶段 P1 和 P2,P1 有一个程序集 AssP1,P2 有一个程序集 AssP2。当我单击“Affaire 中的所有程序集”按钮时,会显示 Affaire 中所有程序集的列表,假设我的方法 Affaire.getAssemblies 使 GroupBy 在 Phase1 和 Phase2 中获取程序集。没看懂你在ItemsSource中加“ph”是什么意思,source是绑定在SelectedPhase上的吧
    猜你喜欢
    • 1970-01-01
    • 2012-11-15
    • 2011-04-10
    • 1970-01-01
    • 2014-01-14
    • 2019-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多