【问题标题】:Adding to ObservableCollection添加到 ObservableCollection
【发布时间】:2011-11-16 05:33:28
【问题描述】:

如果我在一个页面中有一个可观察的集合,可以在列表视图中插入项目。如何从不同的窗口(类)添加到同一个 observablecollection(listview)?我不想使用 INotifyPropertyChanged 和所有这些。我要做的就是将一个项目添加到现有的列表视图中。我已经尝试了一切,但我无法弄清楚。请任何帮助表示赞赏。

CampersPage...(BindingCamper 只是我基本上说 new ObservableCollection() 的方式

  public partial class CampersPage : Page
{
    MainWindow _parentForm;
    public GridViewColumnHeader currentColumnSorted = null;
    private SortAdorner currentAdorner = null;
    String request1;
    String request2;
    String request3;
    String request4;
   // public ObservableCollection<Camper> Campers { get; private set; }


    public CampersPage(MainWindow parent)
    {
        _parentForm = parent;
        InitializeComponent();
        _parentForm.bindings = new BindingCamper();

        for (int i = 0; i < _parentForm.allCampers.Count; i++)
        {


            if (_parentForm.allCampers[i].getRequest(1) != null && _parentForm.allCampers[i].getRequest(2) != null && _parentForm.allCampers[i].getRequest(3) != null && _parentForm.allCampers[i].getRequest(4) != null)
            {
                request1 = _parentForm.allCampers[i].getRequest(1).getName();
                request2 = _parentForm.allCampers[i].getRequest(2).getName();
                request3 = _parentForm.allCampers[i].getRequest(3).getName();
                request4 = _parentForm.allCampers[i].getRequest(4).getName();

            }

            _parentForm.bindings.Campers.Add(new Camper { FirstName = "" + _parentForm.allCampers[i].getFirstName(), LastName = "" + _parentForm.allCampers[i].getLastName(), Ages = _parentForm.allCampers[i].getAge(), SchoolGrade = _parentForm.allCampers[i].getGrade(), Gender = "" + _parentForm.allCampers[i].getGender(), bindingRequest1 = request1, bindingRequest2 = request2, bindingRequest3 = request3, bindingRequest4 = request4 });
            //DataContext = _parentForm.bindings;
        }

        DataContext = _parentForm.bindings;



    }

---现在我点击一个按钮,然后出现一个新窗口,我想在其中添加一个新的露营者到 CampersPage 的列表视图中。

      public partial class AddNewCamper : Window
{
    MainWindow _parentForm;


    public AddNewCamper(MainWindow parentForm)
    {
        InitializeComponent();
        _parentForm = parentForm;
       // _parentForm.bindings = new BindingCamper();

    }private void btnSubmitNewCamper_Click(object sender, RoutedEventArgs e)
    {
        String firstName = txtNewFirstName.Text;
        String lastName = txtLastName.Text;

        int age;
        int grade;
        String newage = comboNewAge.Text;
        if (firstName != "" && lastName != "" && IsNumber(txtNewGrade.Text) && newage != "")
        {
            age = Convert.ToInt16(newage);
            grade = Convert.ToInt16(txtNewGrade.Text);

            // Create New Camper
            Camper person = new Camper(age, grade, boxNewGender.Text, firstName, lastName);

            _parentForm.allCampers.Add(person);
            //This is just adding the camper to the listview. Not sure if it is actually adding it to the database.
            _parentForm.bindings.Campers.Add(new Camper { FirstName = person.getFirstName(), LastName = person.getLastName(), Ages = person.getAge(), SchoolGrade = person.getGrade() });
            //CampersPage p = new CampersPage(_parentForm);
            DataContext = _parentForm.bindings;

我是否必须以某种方式将 AddNewCamper 的命名空间添加到 xaml 中的 CampersPage 的命名空间?

   <ListView  HorizontalAlignment="Stretch" Margin="0,12" x:Name ="listViewCampers" ItemsSource="{Binding Campers}" DisplayMemberPath="bindMe" IsSynchronizedWithCurrentItem="True" Grid.Column="1">

ObservableCollection 类:

      public partial class BindingCamper  
{  // This class assist in binding campers from listview to the textboxes on the camperspage
    public ObservableCollection<Camper> Campers { get; set; }
    public ObservableCollection<Staff> StaffMembers { get; set; }
    public ObservableCollection<Schedule> schedule { get; set; }
    public ObservableCollection<Group> Groups { get; set; }



   public BindingCamper()
    {
      Campers = new ObservableCollection<Camper>();
      StaffMembers = new ObservableCollection<Staff>();
      schedule = new ObservableCollection<Schedule>();
      Groups = new ObservableCollection<Group>();

   }

【问题讨论】:

  • @parapura,这是一个误导性的陈述。我可以给你上千个例子,没有INotifyPropertyChangedObservableCollection WPF 可以很好地工作。
  • 我正在使用 observableCollection,我只是从未展示过它。 _parentForm.Bindings.Camper。 Camper 是 ObservableCollection
  • 我想我的主要问题是如何在 AddNewCamper 中访问 CampersPage?例如,CampersPage c = new CampersPage() 不起作用
  • 尝试为您的 BindingCamper 类实现 INotifyPropertyChanged 接口。
  • 是的,这不起作用..谢谢您的回复

标签: c# wpf visual-studio observablecollection


【解决方案1】:

我不会声称您错误地使用 WPF,但您肯定会让您的生活变得困难。我建议阅读一下 MVVM 模式 - 它确实使 WPF 开发更容易(这是一个很好的开始 article)。

您目前使用的方法在多个层面上都不正确:

  • 您的窗口/页面需要对彼此有太多了解才能正常工作
  • 其中的结果,是对子窗口中父窗体的依赖(而你真正需要的是对窗口context的依赖,实际上是campers列表
  • 您需要做太多手动通知/设置来实现您的目标(而 WPF 有很好的工具可以自动完成)
  • 您似乎正在通过视图 (MainWindow) 暴露模型 (allCampers)

所有这些都可以通过重新设计来解决:

  1. 您的视图(Main、CampersPage、AddNewCamper)应该依赖于BindingCamper 类(本质上可以是它们的视图模型),而不是相互依赖
  2. BindingCamper 的同一实例应为所有这些设置为 DataContext
  3. 不应手动添加绑定(就像您现在所做的那样);一切都可以(并且应该)从 XAML 完成

考虑到上述情况,您的 CampersPage 类应如下所示:

public partial class CampersPage : Page
{
    public CampersPage(BindingCamper camper)
    {
        InitializeComponent();
        DataContext = camper;
    }
}

它不应该为父窗口初始化数据并设置它的绑定。这是完全错误的。

实际上,这种方法(通过构造函数提供数据上下文)可以用于所有视图类(AddNewCamperMainWindow 也可能)。

现在,当您需要露营者页面时,例如从您的主窗口,它变得非常容易:

public partial class MainWindow : Window
{
    public void ShowCampers()
    {
        var campersPage = new CampersPage((BindingCampers) this.DataContext);
        // show campersPage
    }
}

AddNewCamper 窗口同理。只需传递它的数据上下文。添加新露营者时,将其添加到BindingCamper.Campers 列表(可通过数据上下文获得):

// rest of the btnSubmitNewCamper_Click method elided
Camper person = new Camper(age, grade, boxNewGender.Text, firstName, lastName);
((BindingCamper)this.DataContext).Campers.Add(person);

就是这样。由于数据绑定和可观察收集的组合机制,这个新元素将立即在MainWindowCampersPage 中可见。

编辑:

从数据库中获取露营者的代码应该是带有某种DAO 对象的包装器(作为DAL 的一部分 - 我知道,很多丑陋的流行语,但幸运的是它们都是相关的并且相当明显)。例如,你可以有一个类来处理从数据库中获取露营者:

public class CampersProvider
{
    public IEnumerable<Camper> GetAllCampers()
    {
        // here you put all your code for DB interaction
        // and simply return campers
    }
}

为了给您快速的解决方案,您可以再次将CampersProvider 传递给MainWindow 构造函数,调用GetAllCampters 方法并为BindingCamper 构建可观察集合。但是,这不是非常 MVVM 方法。这些东西通常由视图模型(另一个单独的类)处理,目前您没有。

您发布的代码需要相当多的工作,我认为如果您阅读一些有关 MVVM 模式的知识并尝试将其应用到您的应用程序中,这将是一个不错的主意。

【讨论】:

  • 是的,这听起来确实很容易。我的所有其他信息呢,比如我输入数据库的代码,以及我所有的排序方法。 xaml 会一样吗?感谢您的意见,正如您已经告诉我的那样,这是我的第一个 wpf 项目,哈哈
  • 就像在主窗口中一样,是来自数据库的我的 allcampers 列表。我需要一个 for 循环来在我的 observablecollection 中输入所有这些露营者,这样当程序启动时,所有的名字都会在那里
  • @TMan:至于访问数据库和相关内容的代码 - 这通常属于程序的 DAL(数据访问层)部分。它是业务逻辑的一部分,不在 ViewModel 范围内。请参阅我对如何处理这些东西的编辑。
  • 谢谢我的人......每个人都告诉我 MVVM 是要走的路,但我所有的老师都说 MVC 需要更多。我知道为什么,但无论如何感谢所有输入。不幸的是,我没有时间按照应有的方式修复我的代码。我已经做了明显的修复,现在它正在工作。我看过几个 mvvm 示例,我真的很难掌握如何去做。尤其是 b/c,每个人的例子看起来都不一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 1970-01-01
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-30
相关资源
最近更新 更多