Akgul.Maui.DataGrid不显示属性的问题排查求助
问题:Akgul.Maui.DataGrid 无法显示本地JSON加载的数据
调试确认ObservableCollection<Word>已正确填充数据,但界面仅显示硬编码表头,无内容。使用HttpClient.GetFromJsonAsync获取数据时能正常显示,但本地JSON加载生成集合的方式无效,尝试过数组转换、循环添加、硬编码对象等方法均未解决。
相关代码
GridView 代码
public GridView() { InitializeComponent(); BindingContext = new BaseViewModel(); }
GetJson 代码
public Dictionary<string, string>? Json { get { var filePath = JsonFile.FilePath; return JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(filePath)); } } public ObservableCollection<Word> LoadWords(Dictionary<string, string> _json) { var result = new ObservableCollection<Word>(); foreach (var row in _json) if (JsonFile.FileName == "English.json" && !string.IsNullOrWhiteSpace(row.Key)) result.Add(new Word(row.Key) { English = row.Value, Polish = " ", ToTranslate = " " }); else if (JsonFile.FileName == "Polish.json" && !string.IsNullOrWhiteSpace(row.Key)) result.Add(new Word(row.Key) { Polish = row.Value, English = " ", ToTranslate = " " }); else if (JsonFile.FileName == "Translation.json" && !string.IsNullOrWhiteSpace(row.Key)) result.Add(new Word(row.Key) { ToTranslate = row.Value, English = " ", Polish = " " }); else if (!string.IsNullOrWhiteSpace(row.Key)) result.Add(new Word(row.Key) { ToTranslate = row.Value, English = " ", Polish = " " }); else throw new Exception("Id cannot be null!"); return result; }
BaseViewModel 代码
private bool _isRefreshing; public ObservableCollection<Word> Words { get; set; } public Command RefreshCommand { get; set; } public bool IsRefreshing { get => _isRefreshing; set { _isRefreshing = value; OnPropertyChanged(nameof(IsRefreshing)); } } public BaseViewModel() { var _getJson = new GetJson(); Words=_getJson.LoadWords(_getJson.Json!); RefreshCommand = new Command(async () => { IsRefreshing = true; await Task.Delay(3000); IsRefreshing = false; }); } #region INotifyPropertyChanged implementation public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string property) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); } #endregion INotifyPropertyChanged implementation
DataGrid XAML 代码
<Grid RowDefinitions="*,70"> <dg:DataGrid Grid.Row="0" ItemsSource="{Binding Words}" SelectionEnabled="True" RowHeight="50" HeaderHeight="30" BorderThickness="2" PullToRefreshCommand="{Binding RefreshCommand}" IsRefreshing="{Binding IsRefreshing}"> <dg:DataGrid.NoDataView> <Label Text="Nothing to see here!" HorizontalOptions="Center" VerticalOptions="Center" /> </dg:DataGrid.NoDataView> <dg:DataGrid.Columns> <dg:DataGridColumn Title="Id" PropertyName="Id" HorizontalContentAlignment="Center" /> <dg:DataGridColumn Title="English" PropertyName="English" HorizontalContentAlignment="Center" /> <dg:DataGridColumn Title="Polish" PropertyName="Polish" HorizontalContentAlignment="Center" /> <dg:DataGridColumn Title="Translation" PropertyName="ToTranslate" HorizontalContentAlignment="Center" /> </dg:DataGrid.Columns> <dg:DataGrid.RowsBackgroundColorPalette> <dg:PaletteCollection> <Color>#F4F4F4</Color> <Color>#FFFFFF</Color> </dg:PaletteCollection> </dg:DataGrid.RowsBackgroundColorPalette> </dg:DataGrid> </Grid>
排查原因与解决方法
核心问题分析
- 绑定通知缺失:
Words集合在构造函数中直接赋值,未触发PropertyChanged事件。虽然ObservableCollection自身会在内容变化时通知,但初始化时的赋值操作如果没有属性变更通知,UI可能无法感知集合已就绪。 - Word类属性无通知:如果
Word类的Id、English等属性未实现INotifyPropertyChanged,DataGrid无法正确绑定到属性值。 - 同步加载阻塞UI:本地文件读取是同步操作,可能在UI线程阻塞导致绑定流程异常。
具体解决步骤
步骤1:给Word类添加属性变更通知
public class Word : INotifyPropertyChanged { private string _id; private string _english; private string _polish; private string _toTranslate; public string Id { get => _id; set { _id = value; OnPropertyChanged(nameof(Id)); } } public string English { get => _english; set { _english = value; OnPropertyChanged(nameof(English)); } } public string Polish { get => _polish; set { _polish = value; OnPropertyChanged(nameof(Polish)); } } public string ToTranslate { get => _toTranslate; set { _toTranslate = value; OnPropertyChanged(nameof(ToTranslate)); } } public Word(string id) { Id = id; } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
步骤2:修改BaseViewModel的Words属性,添加变更通知
private ObservableCollection<Word> _words; public ObservableCollection<Word> Words { get => _words; set { _words = value; OnPropertyChanged(nameof(Words)); } }
步骤3:异步加载本地数据(避免UI阻塞)
public BaseViewModel() { RefreshCommand = new Command(async () => { IsRefreshing = true; await LoadWordsAsync(); IsRefreshing = false; }); // 初始化时异步加载数据 _ = LoadWordsAsync(); } private async Task LoadWordsAsync() { await Task.Run(() => { var _getJson = new GetJson(); Words = _getJson.LoadWords(_getJson.Json!); }); }
步骤4:验证属性名匹配
确认DataGridColumn的PropertyName与Word类属性名完全一致(大小写敏感),当前代码已匹配,无需修改。
验证方法
完成修改后重新调试:
- 确认
Words赋值时触发PropertyChanged事件 - 确认
Word类属性赋值时触发通知 - 检查UI是否正常显示数据
内容的提问来源于stack exchange,提问作者Ksenonowy
相关产品推荐
相关产品推荐

