从 ViewModel 更改时,Datagrid 将不会更新

问题描述 投票:0回答:1

我有一个

DataGrid
,其中
ItemsSource
绑定到
DataTable
。当我更新
DataTable
时,来自
ViewModel
的数据会更新,但 UI 不会更新。我已经将
INotifyPropertyChanged
用于我的
ViewModel
。 这是我的功能

 private DataTable hariKerjaTable;
 public DataTable HariKerjaTable
 {
     get => hariKerjaTable;
     set
     {
         hariKerjaTable = value; 
         OnPropertyChanged(nameof(HariKerjaTable));
     }
 }
 private DataTable kalenderKerjaTable;
 public DataTable KalenderKerjaTable
 {
     get => kalenderKerjaTable;
     set
     {
         kalenderKerjaTable = value;
         OnPropertyChanged(nameof(KalenderKerjaTable));
     }
 }

private async void GetWorkingCalendar()
{
    HariKerjaTable.Clear();
    KalenderKerjaTable.Columns.Clear();
    KalenderKerjaTable.Rows.Clear();

    var data = new
    {
        month = Month,
        year = Year,
    };

    string get = await BaseAPI.PostMethod("calendar/select", JsonConvert.SerializeObject(data));
    if (get is not null)
    {
        JObject jsonObject = JObject.Parse(get);
        JToken dataToken = jsonObject["data"];
        HariKerjaTable = dataToken.ToObject<DataTable>();
    }
    else
    {
        MessageBox.Show("Something wrong when retrieving", "Null", MessageBoxButton.OK, MessageBoxImage.Error);
    }

    Application.Current.Dispatcher.Invoke(() =>
    {
        foreach (DataRow row in HariKerjaTable.Rows)
        {
            DateTime date = DateTime.Parse(row["date_calendar"].ToString());
            Debug.WriteLine(date.ToString("ddd\ndd"));
            if (!KalenderKerjaTable.Columns.Contains(date.ToString("ddd\ndd")))
            {
                KalenderKerjaTable.Columns.Add(date.ToString("ddd\ndd"));
            }
        }
        OnPropertyChanged(nameof(KalenderKerjaTable));
    });

    Debug.WriteLine("+++++++++++++++++++++++++++++++");
    foreach (DataColumn column in KalenderKerjaTable.Columns)
    {
        Debug.WriteLine(column.ColumnName);
    }
}

这是我的 XAML

<Grid Grid.Row="1" Margin="0,5,0,0">
    <DataGrid ItemsSource="{Binding KalenderKerjaTable, Mode=TwoWay}" FrozenColumnCount="2" AutoGenerateColumns="True"/>
</Grid>

我尝试将

Mode=TwoWay
UpdateSourceTrigger=PropertyChanged
添加到 XAML,但它没有改变任何内容。

c# wpf mvvm
1个回答
0
投票

首先,我们永远不应该声明

async void
方法,因为它为许多不同的错误打开了大门。唯一的例外是事件处理程序。始终返回
Task
Task<TResult>
:

// Serious code smell
private async void GetWorkingCalendar();

// Correct signature
private async Task GetWorkingCalendarAsync();

接下来,

Dispatcher.Invoke
是多余的:DataTable不会扩展
DispatcherObject
并且设置引发
INotifyPropertyChanged.PropertyChnaged
的属性从来都不是问题,因为绑定引擎会将事件编组到正确的调度程序线程。

此外,您应该使用

System.Text.Json
API,因为它提供了异步 API:.NET 中的 JSON 序列化和反序列化(编组和解组) - 概述

TwoWay
绑定到
ItemsControl.ItemsSource
上没有任何意义,因为
ItemsControl
永远不会更改设置为
IEnumerable
属性的
ItemsSource
实例。
一般来说,对
ItemsSource
属性的绑定应该是
OneTime

解决您的主要问题,单独提高

PropertyChanged
没有帮助,因为实例仍然相同。仅当旧值和新值不是同一个实例时,绑定到属性的依赖属性才会更新自身。

您必须替换实例(保存

DataTable
的属性值)或重置它。

private async Task GetWorkingCalendarAsync()
{
  ...

  bool hasChanges;
  foreach (DataRow row in HariKerjaTable.Rows)
  {
    DateTime date = DateTime.Parse(row["date_calendar"].ToString());
    Debug.WriteLine(date.ToString("ddd\ndd"));
    if (!KalenderKerjaTable.Columns.Contains(date.ToString("ddd\ndd")))
    {
      hasChanges = true;
      KalenderKerjaTable.Columns.Add(date.ToString("ddd\ndd"));
    }
  }
  
  if (hasChanges)
  {
    // Option 1: replace
    KalenderKerjaTable = KalenderKerjaTable.DefaultView.ToTable();

    // Option 2: reset
    var tableTemp = KalenderKerjaTable;
    KalenderKerjaTable = null;
    KalenderKerjaTable = tableTemp;
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.