当可观察集合发生变化时,列表视图不会得到更新

The listview don't get update when the observable collection changes

这是列表视图

    <ListView x:Name="task_list" SelectionChanged="task_list_SelectionChanged"  Grid.Row="0" Grid.Column="1"  Background="Transparent">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:TaskTodo">
                <TextBlock Width="100" Foreground="White" Text="{x:Bind NameTask}"  />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

和视图模型

public class TaskTodo : INotifyPropertyChanged
{
    private string _NameTask, _Reminder, _Date, _Priority, _NameList, _Description;
    private int _Id, _ParentTask;
    
    private DateTimeOffset _NextRep;
    public TaskTodo()
    {        
      _NameTask =   String.Empty;
      _Reminder  =  String.Empty;
      _Date =       String.Empty;
      _Priority  =  String.Empty;
      _NameList  =  String.Empty;
      _Description = String.Empty;
     _ParentTask =  -1;
     _Id = 1;
    }

    Resource_Manager rm = new Resource_Manager();
    public event PropertyChangedEventHandler PropertyChanged;
    TaskSqliteDataAccess TaskSqlite = new TaskSqliteDataAccess();

    private void NotifyPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    public int TaskId { get { return _Id; }  set { _Id = value; NotifyPropertyChanged(TaskId.ToString()); } }
    public string NameTask { get { return _NameTask; } set { _NameTask = value; NotifyPropertyChanged(NameTask); } }
    public string Reminder { get { return _Reminder; } set { _Reminder = value; NotifyPropertyChanged(FormatDateReminder); } }
    public string NameList {  
        get 
        {
            if ( _NameList == string.Empty || _NameList == null)
            {
                return rm.GetDefaultNamelist;
            }
            return _NameList;

            }
        set { _NameList = value; NotifyPropertyChanged(NameList); }
    }

       
    public string Date { get { return _Date ; } set { _Date = value; NotifyPropertyChanged(FormatDate); } }
    public string FormatDate
    {
        get
        {
            var cultureInfo = new CultureInfo("en-US");
            DateTimeOffset DueDate;
            
            if (Date != string.Empty && Date != null)
            {
                DueDate = DateTimeOffset.Parse(Date, cultureInfo);
                return String.Format(" {0},{1} {2}", DueDate.DayOfWeek, DueDate.Day, DueDate.ToString("MMM"));
            }
            else                   
                return rm.GetDefaultDate;             
        }
         
}
    public string Priority { get { return _Priority; } set { _Priority = value; NotifyPropertyChanged(Priority); } }
    public string Description { get { return _Description;  } set { _Description = value; NotifyPropertyChanged(Description); } } 
    public DateTimeOffset NextRep { get { return _NextRep; } set { _NextRep= value; NotifyPropertyChanged(NextRep.ToString()); } }      
    public int  ParentTask { get { return _ParentTask; } set { _ParentTask = value; NotifyPropertyChanged(TaskId.ToString()); } }      
    public string FormatTimeReminder
    {
        get {
            DateTime Time;
            var cultureInfo = new CultureInfo("en-US");
            if ( Reminder != string.Empty && Reminder !=  null )
            {
                Time = DateTime.Parse (Reminder, cultureInfo);
                return string.Format(" Remind me at {0}:{1}", Time.Hour, Time.Minute);
            }
                          
            return rm.GetDefaultReminder;
            
        } 
    }
    public string FormatDateReminder
    {
        get
        {
            DateTimeOffset Date;

            if(DateTimeOffset.TryParse(_Reminder, out Date) == true)
            {
                return string.Format(" {0},{1} {2}", Date.DayOfWeek, Date.Day, Date.ToString("MMM"));

            }

            return Reminder;

        }
    }
    public ObservableCollection<TaskTodo> GetTasks() => TaskSqlite.GetTaskDB();
 
    public void AddTask(TaskTodo task) => TaskSqlite.AddTaskDB(task); 

    public void UpdateTask() => TaskSqlite.UpdateData(TaskId, NameTask, Date, Reminder, Priority, NameList, Description, NextRep);
  
    public ObservableCollection<TaskTodo> GetSubtasks(TaskTodo taskTodo) => TaskSqlite.GetSubtasks(taskTodo);

例如,如果我更改表单中的 NameTask 属性,属性 会更改,并且如果将 属性 绑定到表单中的 texblock,texblock 将具有新的值,但列表视图的 texblock 没有

StackPanel Name="TaskForm"  Grid.Column="2" Width="340" Background="#04000E" HorizontalAlignment="Right" Visibility="Collapsed" >
        <Button FontSize="20" Name="quit_TaskForm" Content="x" Click="quit_TaskForm_Click" HorizontalAlignment="Right" Background="Transparent"></Button>

        <TextBox Name="NameTaskForm" HorizontalAlignment="Center" FontSize="20" 
                 TextChanged="NameTaskForm_TextChanged" LostFocus="NameTaskForm_LostFocus" Foreground="White" 
                 DataContext="{Binding ElementName=task_list, Path=SelectedItem}" 
                 Text="{Binding Path=NameTask, Mode=TwoWay}"
                 Style="{StaticResource TextBoxStyle1}" BorderThickness="0"  />
       
    
        </StackPanel>

这是表单文本框文本发生变化时的事件代码

 private void NameTaskForm_TextChanged(object sender, TextChangedEventArgs e)
    {
        if ((task_list.SelectedItem as TaskTodo)!= null)
        {
            (task_list.SelectedItem as TaskTodo).NameTask = NameTaskForm.Text;
            (task_list.SelectedItem as TaskTodo).UpdateTask();

           
        }

        
    }

NotifyPropertyChanged 方法采用 属性 的名称,而不是它的值 ... NotifyPropertyChanged(NameTask); 这应该改为 NotifyPropertyChanged(nameof(NameTask));

如这一行

 public string NameTask { get { return _NameTask; } set { _NameTask = value; NotifyPropertyChanged(NameTask); } }

应该是这样的

public string NameTask { get { return _NameTask; } set { _NameTask = value; NotifyPropertyChanged(nameof(NameTask)); } }

所以你必须在每次调用 NotifyPropertyChanged 时编辑所有代码,以给它你更改的 属性 的名称......或者你可以让编译器自动获取调用者 属性 名称只是使用 CallerMemberName 属性

using System.Runtime.CompilerServices;
//...
void OnPropertyChanged([CallerMemberName] string name = null)
{
   PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

并在不传递任何值的情况下调用它,编译器会自动获取调用者姓名

如下

public string NameTask 
{ 
  get { return _NameTask; } 
  set 
  {
     _NameTask = value;
     NotifyPropertyChanged(); // without passing any value
   }
}