添加到 ObservableCollection

发布于 2024-12-15 12:32:30 字数 4413 浏览 1 评论 0原文

如果我在页面中有一个可观察集合,该集合在列表视图上插入项目。如何从不同的窗口(类)添加到同一个可观察集合(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;



    }

---现在我单击一个按钮,会出现一个新窗口,我想在其中添加一个新的 Camper 到 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">

      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>();

   }

If I have a observablecollection in a page that inserts items on a listview. How can I add to that same observablecollection(listview) from a different window(class)? I do not want to use INotifyPropertyChanged and all that. All I'm trying to do is add a item to the existing listview. I have tried literally everything and I can't figure it out. Please any help is appreciated.

CampersPage...(BindingCamper is just my way of basically saying 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;



    }

---Now I click on a button and a new window comes up where I would like to add a new camper to the listview in 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;

Do I have to somehow add AddNewCamper's namespace to CampersPage's namespace in xaml?

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

ObservableCollection class:

      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>();

   }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

纵山崖 2024-12-22 12:32:31

我不会声称您错误地使用了 WPF,但您确实让您的生活变得困难。我建议阅读一些 MVVM 模式 - 它确实使 WPF开发更容易(这里有一篇很好的入门文章)。

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

  • 您的窗口/页面需要对彼此有太多了解才能正常工作,
  • 其结果是依赖于您的父表单子窗口(而您真正需要的是对窗口上下文的依赖,实际上是露营者列表),
  • 您需要执行太多的手动通知/设置才能实现您的目标(虽然 WPF 有很好的工具可以自动执行此操作)
  • 您似乎是通过视图 (MainWindow) 公开模型 (allCampers)

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

  1. 您的视图 (Main、CampersPage、AddNewCamper) 应该依赖于 < code>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 模式的内容并尝试将其应用到您的应用程序中,这不会是一个坏主意。

I won't go as far as claiming you're using WPF wrong, but you're certainly making your life difficult. I suggest reading up a bit on MVVM pattern - it really makes WPF development easier (here's good starting article).

Approach you're using at the moment is not correct on several levels:

  • your windows/pages need to have way too much knowledge about each other to work properly
  • result of which, is dependency on parent form in your child windows (while what you really need is dependency on window context, which in fact is campers list)
  • you need to do too much manual notifications/setting up to achieve your goals (while WPF has great tools to do it automatically)
  • you seem to be exposing model (allCampers) through view (MainWindow)

All of this can be solved with a bit of redesigning:

  1. Your views (Main, CampersPage, AddNewCamper) should be dependent on BindingCamper class (which essentially could be view model for them), not on each other
  2. Same instance of BindingCamper should be set as DataContext for all of them
  3. You should not add bindings manually (like you're doing now); all can (and should) be done from XAML

Having above in mind, your CampersPage class should look like this:

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

It should by no means initialize data for parent window and set it's binding. This is simply wrong.

Actually, this approach (providing data context through constructor) can be used in all your view classes (AddNewCamper and MainWindow too, probably).

Now, when you need campers page, say from your main window, it gets very easy:

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

It is the same with AddNewCamper window. Just pass it data context. When you add new camper, add it to BindingCamper.Campers list (which is available through data context):

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

That's all. Thanks to combined mechanisms of data binding and observable collection, this new element will immediately be visible both in MainWindow and CampersPage.

Edit:

Code to fetch campers from database should be wrapper with some kind of DAO object (as a part of DAL - I know, lot of ugly buzzwords, but luckily they are all related and fairly obvious). For example, you can have a class that will deal with getting campers from database:

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

To give you quick solution, you can once again pass CampersProvider to MainWindow constructor, call GetAllCampters method and build observable collection for BindingCamper. However, this is not very MVVM approach. Those stuff usually is handled by view model (yet another, separate class), which at the moment you don't have.

Code you posted requires quite some work, I think it won't be a bad idea if you read a bit about MVVM pattern and try to apply it to your application.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文