简体   繁体   English

C# wpf listview 绑定问题与可观察集合

[英]C# wpf listview binding problem with observable collection

I followed this Tutorial to create an Calendar/Schedule: https://www.codeproject.com/Articles/35490/Creating-the-Microsoft-Outlook-Appointment-View-in The Listview contains 5 Items, source我按照这个教程创建了一个日历/计划: https ://www.codeproject.com/Articles/35490/Creating-the-Microsoft-Outlook-Appointment-View-in Listview包含5个项目,源

<!--<ListView.Items>
                <local:Termin Start="10/28/2021 6:00 AM" Finish="10/28/2021 4:00 PM" Subject="Meet with John" Location="Southwest Meeting Room" Organizer="Jim Smith" />
                <local:Termin Start="10/29/2021 6:00 AM" Finish="10/29/2021 4:00 PM" Subject="Meet with Rick" Location="Southwest Meeting Room" Organizer="Jim Smith" />
                <local:Termin Start="10/30/2021 6:00 AM" Finish="10/30/2021 6:00 PM" Subject="Meet with Dave" Location="Southwest Meeting Room" Organizer="Jim Smith" />
                <local:Termin Start="10/31/2021 6:00 AM" Finish="10/31/2021 6:00 PM" Subject="Meet with Larry" Location="Southwest Meeting Room" Organizer="Jim Smith" />
                <local:Termin Start="10/31/2021 6:00 AM" Finish="10/31/2021 6:00 PM" Subject="Meet with Jim" Location="Southwest Meeting Room" Organizer="Jim Smith" />
            </ListView.Items>-->

Now , as i try to replace the hardcoded Items with an observable collection现在,当我尝试用可观察的集合替换硬编码的项目时

        <ListView  ItemsSource="{Binding Termine}">
            <ListView.View>
                <controls:CalendarView ItemBeginBinding="{Binding Start}" ItemEndBinding="{Binding Finish}">
`
public class KalenderVM : BewohnerVM
    {
        public KalenderVM()
        {
            DateTime dateValue1;
            DateTime dateValue2;
            DateTime.TryParse("25.10.2021 6:00", out dateValue1);
            DateTime.TryParse("25.10.2021 16:00", out dateValue2);
            Termine.Add(new Termin(dateValue1, dateValue2, "Jan", "Anker"));
            DateTime.TryParse("26.10.2021 6:00", out dateValue1);
            DateTime.TryParse("26.10.2021 16:00", out dateValue2);
            Termine.Add(new Termin(dateValue1, dateValue2, "Jan", "Anker"));
            DateTime.TryParse("27.10.2021 6:00", out dateValue1);
            DateTime.TryParse("27.10.2021 18:00", out dateValue2);
            Termine.Add(new Termin(dateValue1, dateValue2, "Jan", "Frei"));
}
        private ObservableCollection<Termin> _termine = new ObservableCollection<Termin>();
        public ObservableCollection<Termin> Termine
        {
            get { return _termine; }
            set { _termine = value; }
        }
public partial class Kalender : UserControl
    {
        public Kalender()
        {
            InitializeComponent();
        }
    }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IWHRManagment.Models
{
    public class Termin
    {
        public Termin(DateTime start, DateTime finish, string orga, string sub)
        {
            Start = start;
            Finish = finish;
            Organizer = orga;
            Subject = sub;
            Location = "Home";
        }
        public Termin() { }
        public DateTime Start { get; set; }
        public DateTime Finish { get; set; }
        public bool Recurring { get; set; }
        public object Interval { get; set; }
        public string Organizer { get; set; }
        public string Subject { get; set; }
        public string Location { get; set; }
    }
}

The ListView contains 2 Items (i created 2 for test purpose) but no items are shown cause "Start" and "Finish" are "not found in the ViewModel" .... I tried a static ressource, several relativ sources but i still have troubles to do it the right way. ListView 包含 2 个项目(我为测试目的创建了 2 个)但没有显示项目,因为“开始”和“完成”“在 ViewModel 中找不到”......我尝试了一个静态资源,几个相对来源,但我仍然有困难以正确的方式去做。

Could someone pls help me out and show me the correct way ?有人可以帮助我并告诉我正确的方法吗?

This is a simple LV in MVVM.这是 MVVM 中的一个简单 LV。 You've got a little mess in naming: just keep to xxxViewModel etc;你在命名方面有点混乱:只要保持xxxViewModel等; don't make shortcuts.不要走捷径。

I'm pasting simple MVVM example of simple ListView, which is wrapped by an ItemViewModel class and bound by XAML.我正在粘贴简单 ListView 的简单 MVVM 示例,该示例由 ItemViewModel 类包装并由 XAML 绑定。

If you're not aware of dangers, don't start your job from user controls.如果您没有意识到危险,请不要从用户控制开始您的工作。 They need different treatment and binding.他们需要不同的处理和绑定。

Intentionally, I wrapped a basic model (databaseentry) object with a ViewModel.我特意用 ViewModel 包装了一个基本模型(databaseentry)对象。 In the future, it's easier to update properties and you won't trouble yourself with 'how to add inotifychanged to entityframework'.将来,更新属性会更容易,而且您不会为“如何将 inotifychanged 添加到实体框架”而烦恼。 More boilerplate, but I hope it'll work.更多样板,但我希望它会起作用。

If you don't understand some things, then try to.如果你不明白一些事情,然后尝试。 There are hacks.有黑客。 If you init viewmodel from 'xaml', as I did here, then don't declare datacontext = new AnyViewModel() because you will fail.如果你从 'xaml' 初始化视图模型,就像我在这里所做的那样,那么不要声明datacontext = new AnyViewModel()因为你会失败。

In general, I see MVVM as a poor choice.总的来说,我认为 MVVM 是一个糟糕的选择。 The bindings are a thing that were always lacking in WinForms/QT, and here they are.绑定是 WinForms/QT 中一直缺乏的东西,现在它们来了。 But since you've got bindings you start to struggle and struggle with communication, then you add and add classes, data classes, services, and bla bla.但是既然你有了绑定,你就开始在通信上挣扎和挣扎,然后你添加和添加类、数据类、服务和 bla bla。 The more someone goes into templates and generics the more code becomes a mess.越多的人使用模板和泛型,越多的代码变得一团糟。

VIEWMODEL (integrated for simplicity): VIEWMODEL(为简单起见集成):

using Pjoter2000.View;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Pjoter2000.ViewModel
{
    public class DatabaseEntry // EntityFramework as an example
    {
        public int ID { get; set; }
        public string DataName { get; set; }
    }

    // MVVM wrapper for single item, Inotifypropertychanged should be a class that simplifiesr wrapping
    public class SomeItemViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        private DatabaseEntry _item;

        public string Name
        {
            get => _item.DataName;
            set
            {
                _item.DataName = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
            }
        }

        SomeItemViewModel() { } //wtf? :)

        public SomeItemViewModel(DatabaseEntry entry)
        {
            _item = entry;
        }
    }

    public class PoligonViewModel
    {
        ObservableCollection<SomeItemViewModel> _records;
        public ObservableCollection<SomeItemViewModel> Records
        {
            get => _records;
            set
            {
                _records = value;
            }
        }

        public PoligonViewModel()
        {
            // INIT Records
            Records = new ObservableCollection<SomeItemViewModel>();

            // Fetching data from model (DB), abstract
            for (int i = 0; i < 10; i++)
            {
                var item = new DatabaseEntry()
                {
                    DataName = "Name " + i.ToString()
                };

                // Wrapping database model data into itemviewmodel (some say it's more flexible and might be ok in future)
                Records.Add(new SomeItemViewModel(item));
            }
        }
    }
}

VIEW:看法:

using System.Windows;

namespace Pjoter2000.View
{
    public partial class Poligon : Window
    {      
        public Poligon()
        {
            InitializeComponent(); // Current data context is poligonviewmodel, because it's set from xaml already           
        }
    }
}

XAML XAML

<Window x:Class="Pjoter2000.View.Poligon"
        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:viewmodel="clr-namespace:Pjoter2000.ViewModel"
        mc:Ignorable="d"
        Title="Poligon" Height="400" Width="514">

    <Window.DataContext>
        <!-- THIS PART CREATES VIEW MODEL CLASS, DON'T CREATE IT IN CONSTRUCTOR -->
        <viewmodel:PoligonViewModel/>
    </Window.DataContext>
    <Grid>
        <ListView ItemsSource="{Binding Records}">
            <!-- This is the main view of the list, so I declare the view here -->
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM