繁体   English   中英

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

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

我按照这个教程创建了一个日历/计划: 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>-->

现在,当我尝试用可观察的集合替换硬编码的项目时

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

ListView 包含 2 个项目(我为测试目的创建了 2 个)但没有显示项目,因为“开始”和“完成”“在 ViewModel 中找不到”......我尝试了一个静态资源,几个相对来源,但我仍然有困难以正确的方式去做。

有人可以帮助我并告诉我正确的方法吗?

这是 MVVM 中的一个简单 LV。 你在命名方面有点混乱:只要保持xxxViewModel等; 不要走捷径。

我正在粘贴简单 ListView 的简单 MVVM 示例,该示例由 ItemViewModel 类包装并由 XAML 绑定。

如果您没有意识到危险,请不要从用户控制开始您的工作。 他们需要不同的处理和绑定。

我特意用 ViewModel 包装了一个基本模型(databaseentry)对象。 将来,更新属性会更容易,而且您不会为“如何将 inotifychanged 添加到实体框架”而烦恼。 更多样板,但我希望它会起作用。

如果你不明白一些事情,然后尝试。 有黑客。 如果你从 'xaml' 初始化视图模型,就像我在这里所做的那样,那么不要声明datacontext = new AnyViewModel()因为你会失败。

总的来说,我认为 MVVM 是一个糟糕的选择。 绑定是 WinForms/QT 中一直缺乏的东西,现在它们来了。 但是既然你有了绑定,你就开始在通信上挣扎和挣扎,然后你添加和添加类、数据类、服务和 bla bla。 越多的人使用模板和泛型,越多的代码变得一团糟。

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

看法:

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

<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