当可观察集合更改时,列表视图不会更新

发布于 2025-01-11 01:22:57 字数 5834 浏览 0 评论 0原文

例如

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

,如果我更改表单中的 NameTask 属性,则该属性会

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

更改,并且如果将该属性绑定到表单中的 texblock,则 texblock 具有新值,但 listview 的 texblock 不会t

在此处输入图像描述

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

           
        }

        
    }

this the listview

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

And the view model

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

For example if I change the NameTask property in the form, the property changes , and if bind that property to the texblock from the form, the texblock have the new value but the the texblock of the listview don't

enter image description here

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>

this the code of the event when the text of the texbox from the form changes

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

           
        }

        
    }

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

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

发布评论

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

评论(1

坠似风落 2025-01-18 01:22:57

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

NotifyPropertyChanged Method Takes the name of the property, not the value of it ...
NotifyPropertyChanged(NameTask);
this should be change to
NotifyPropertyChanged(nameof(NameTask));

as in this line

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

should be like this

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

so you have to edit all your code whenever you call NotifyPropertyChanged to give it the name of the property you change ... or you can make the compiler automatically get the caller property name just use CallerMemberName attribute

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

and call it without passing any value and the compiler automatically get the caller name

as following

public string NameTask 
{ 
  get { return _NameTask; } 
  set 
  {
     _NameTask = value;
     NotifyPropertyChanged(); // without passing any value
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文