Xaml 更新可观察集合中的对象时视图未更新

Xaml view not updating while updating objects in observable collection

虽然我对 xaml 和 C# 完全陌生,但我正在尝试开始使用 UWP 应用程序。这个问题现在已经花费了我几个小时。我已经看过很多教程并在 Whosebug 上阅读了类似问题的答案,但到目前为止对我没有任何帮助。

我有一个 ListView,它具有到 ObservableCollection 的数据绑定。当我启动应用程序时,它会正确显示此集合中的对象。当我向集合中添加新对象或删除现有对象时,ListView 会正确更新。但是当我修改对象时,它不会更新,尽管我实现了 INotify属性Changed 并在 属性 更改时触发事件。

代码如下:

查看Xaml

<Page
x:Class="Prophecy_Challenge_Tracker.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Prophecy_Challenge_Tracker"
xmlns:data="using:Prophecy_Challenge_Tracker.persistence"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel x:Name="firstStack" Margin="8 ,32 ,0, 0 " Width="350" >
        <ListView ItemsSource="{x:Bind ViewModel.Collection}"   VerticalAlignment="Center" Background="Yellow" CanReorderItems="True">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="data:Challenge" >
                    <Grid  Background="Green" >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="50"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Button  Content="+" Grid.Column="0"/>
                        <TextBlock  Grid.Column="1" Text="{x:Bind ChallengeName}" VerticalAlignment="Center"/>
                        <TextBlock Grid.Column="2"  Text="{x:Bind Progress}" VerticalAlignment="Center" HorizontalAlignment="Center" />
                        <Button Grid.Column="3" Content="X"  />
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <Button Content="Add" Click="add"/>
        <Button Content="Delete" Click="delete"/>
        <Button Content="Update Progress" Click="updateProgress"/>
    </StackPanel>
</Grid>

代码隐藏

    using Prophecy_Challenge_Tracker.persistence;
using Prophecy_Challenge_Tracker.viewmodel;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace Prophecy_Challenge_Tracker
{
    /// <summary>
    /// Eine leere Seite, die eigenständig verwendet oder zu der innerhalb eines Rahmens navigiert werden kann.
    /// </summary>
    public sealed partial class MainPage : Page
    {

        public MainPage()
        {
            this.ViewModel = new Viewmodel();
            this.InitializeComponent();
            this.DataContext = ViewModel;
        }

        public Viewmodel ViewModel { get; set; }

        int counter = 2;
        private void add(object sender, RoutedEventArgs e)
        {
            counter++;
            var c = new Challenge();
            c.ChallengeName = "Additional Line";
            c.Progress = counter + "/7";
            ViewModel.Collection.Add(c);
        }

        private void delete(object sender, RoutedEventArgs e)
        {
         var c =   ViewModel.Collection.ElementAt(ViewModel.Collection.Count - 1);
            ViewModel.Collection.Remove(c);
            counter--;
        }

        private void updateProgress(object sender, RoutedEventArgs e)
        {
            var c = ViewModel.Collection.ElementAt(ViewModel.Collection.Count - 1);
            int index = ViewModel.Collection.IndexOf(c);
            counter++;
            Debug.WriteLine("CurrentName: " + c.Progress);
            c.Progress = counter + "/7";
            Debug.WriteLine("New Name: " + c.Progress);
        }
    }
}

对象Class

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Prophecy_Challenge_Tracker.persistence
{
    public class Challenge : INotifyPropertyChanged
    {
        private string challengeName;
        public string ChallengeName
        {
            get { return challengeName; }
            set
            {
                if (value != challengeName)
                {
                    challengeName = value;
                    NotifyPropertyChanged("ChallengeName");
                }
            }
        }

        private string progress = "";
        public string Progress
        {
            get { return progress; }
            set
            {
                if (value != progress)
                {
                    progress = value;
                    NotifyPropertyChanged("Progress");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
        {
            System.Diagnostics.Debug.WriteLine("Shortly before update. PropertyName = " + propertyName);
            if (PropertyChanged != null)
            {
                System.Diagnostics.Debug.WriteLine("Update now");
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

视图模型

using Prophecy_Challenge_Tracker.persistence;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Prophecy_Challenge_Tracker.viewmodel
{
    public class Viewmodel
    {

        public ObservableCollection<Challenge> Collection { get; set; }

        public Viewmodel()
        {
            System.Diagnostics.Debug.WriteLine("New Viewmodel is being created");
            Collection = new ObservableCollection<Challenge>();
            Challenge c = new Challenge();
            c.ChallengeName = "First Line";
            c.Progress = "1/5";
            Collection.Add(c);
            c = new Challenge();
            c.ChallengeName = "Second Line";
            c.Progress = "2/5";
            Collection.Add(c);
        }
    }
}

编译绑定默认为 OneTime,因此它们仅在初始时设置,不会侦听更改。

改为:

<ListView ItemsSource="{x:Bind ViewModel.Collection, Mode=OneWay}">...

this Build session.

中找到关于编译绑定的很好的概述