【问题标题】:Binding Task<List<T>> to DataGrid WPF C#将 Task<List<T>> 绑定到 DataGrid WPF C#
【发布时间】:2022-01-30 20:13:40
【问题描述】:

我的问题是我试图在我的 WPF 应用程序中将 Task 绑定到 DataGrid,但我不明白问题是什么以及我做错了什么。 我有 3 个模型

学科组教师:

public class DisciplineGroupTeacher
{
     [JsonPropertyName("iddiscipline-group-teacher")]
     public int IdDisciplineGroupTeacher { get; set; }
     [JsonPropertyName("idteacher")]
     public int? IdTeacher { get; set; }
     [JsonPropertyName("iddiscipline")]
     public int IdDiscipline { get; set; }
     [JsonPropertyName("idgroup")]
     public int IdGroup { get; set; }
     public async Task<Teacher> Teacher() => await DataWorker.GetTeacher(IdTeacher);
     public async Task<Group> Group() => await DataWorker.GetGroup(IdGroup);
     public async Task<Discipline> Discipline() => await DataWorker.GetDiscipline(IdDiscipline);
}

老师:

public class Teacher
{
    [JsonPropertyName("idteacher")]
    public int IdTeacher { get; set; }
    [JsonPropertyName("name")]
    public string Name { get; set; }
}

组:

public class Group
{
    [JsonPropertyName("idgroup")]
    public int IdGroup { get; set; }
    [JsonPropertyName("group_name")]
    public string Name { get; set; }
    [JsonPropertyName("iddepartment")]
    public int IdDepartment { get; set; }
}

纪律:

public class Discipline
{
    [JsonPropertyName("iddiscipline")]
    public int IdDiscipline { get; set; }
    [JsonPropertyName("discipline_name")]
    public string Name { get; set; }
}

在 Data Worker 中,我有从 API 获取的方法:

public class DataWorker
{
    public static async Task<Teacher> GetTeacher(int? id)
    {
        var client = new HttpClient();
        var streamTask = client.GetStreamAsync($"myurl...");
        var data = await JsonSerializer.DeserializeAsync<Teacher>(await streamTask);
        return data;
    }
    public static async Task<Discipline> GetDiscipline(int id)
    {
        var client = new HttpClient();
        var streamTask = client.GetStreamAsync($"myurl...");
        var data = await JsonSerializer.DeserializeAsync<Discipline>(await streamTask);
            return data;
    }
    public static async Task<Group> GetGroup(int id)
    {
        var client = new HttpClient();
        var streamTask = client.GetStreamAsync($"myurl...");
        var data = await JsonSerializer.DeserializeAsync<Group>(await streamTask);
        return data;
    }
}

在某个事件中,我得到一个 BindingList,在其中我得到一个 List 并绑定到 DataGrid

BindingList<DisciplineGroupTeacher> dgts= new BindingList<DisciplineGroupTeacher>(await DataWorker.GetDisciplineGroupTeachers());
MyDataGrid.ItemsSource = dgts;

在 XAML 中我做绑定

<DataGrid x:Name="MyDatGrid"  AutoGenerateColumns="False" CanUserAddRows="False" ColumnWidth="*" IsReadOnly="True" FontSize="13">
    <DataGrid.Columns>
        <materialDesign:DataGridTextColumn Header="Discipline" Binding="{Binding Discipline.Name}"/>
        <materialDesign:DataGridTextColumn Header="Group"  Binding="{Binding Group.Name}"/>
        <materialDesign:DataGridTextColumn Header="Teacher"  Binding="{Binding Teacher.Name}"/>
    </DataGrid.Columns>
</DataGrid>

但是当我开始时,我需要的字段不会出现在数据网格中。我究竟做错了什么?我最近遇到了异步等待。在此之前,应用程序使用本地数据库,但现在我需要从 API 获取数据。

【问题讨论】:

  • 您可能需要添加 ViewModel,它可以使用像 this 这样的包装类型进行数据绑定。
  • @StephenCleary 我从文档中获取了 NotifyTaskCompletion 类并删除了 INotifyPropertyChanged。我尝试使用此类获取属性的数据:Teacher _Teacher => new TaskCompletion(DataWorker.GetTeacher(IdTeacher)).Result;但结果仍然没有显示在数据网格中。
  • NotifyTaskCompletion 的全部意义在于它实现了INotifyPropertyChanged。所以你的数据绑定会绑定到Teacher.Result,你的代码会绑定Teacher = new NotifyTaskCompletion(DataWorker.GetTeacher(IdTeacher))Resultnull 开头,然后 更改 为异步操作完成时的结果;这就是为什么需要INotifyPropertyChanged
  • 视图模型在哪里?什么是 DataContext?

标签: c# wpf async-await


【解决方案1】:

由于DataContext不清楚,所以很难回答,但总的来说:

您想绑定到 ViewModel 上的 ObservableCollection&lt;T&gt; 属性。

如果此列表是异步生成的,VM 将调用模型上的 async 函数,最终将恢复该列表。在await 调用此调用之后,您将填充 ViewModel 集合(每次集合更改时都会引发事件)或创建一个 new 并手动引发属性更改事件。

async 操作无需使用阻塞等待,如果从 UI 线程完成,通常会导致死锁。

我还注意到您在 DisciplineGroupTeacher 上的方法每次被调用时都会反序列化数据,这可能不是您想要的。

【讨论】:

  • 但我不使用 MVVM 模式。
  • 您使用什么?什么是 DataContext?
【解决方案2】:

问题是您试图绑定到一个不存在的属性。例如,考虑您对Discipline.Name 的第一个绑定。你的DisciplineGroupTeacher 上没有 Discipline 属性,对吗?虽然有Discipline()方法,但(await Discipline()).Name(应该有name值)和Discipline.Name(不存在)是不一样的。

既然我们知道了问题所在,我们该如何解决它。你应该:

  • 为您的班级中的每个元素添加一个属性(例如,添加学科、教师和小组)

  • 在你的数据加载函数中获取每一个的值

如果您无法从您的代码同步运行 Discipline.Name 以获取已从您的数据源中检索到的有效值,那么您的 UI 也不能。

如果其中任何一个没有意义,请告诉我。我很高兴扩展它以确保您可以继续前进。

【讨论】:

  • 感谢您的回复。但问题是我无法将值从 Task 传递给属性。尝试 .Result 时,应用程序冻结
  • @Nasimjon 您无法在 UI 绑定中运行 .Result。你在哪里运行.Result?
  • 据我了解,编写 .Result 根本不可能,因为它会阻止流程。我尝试按照文档link 中的方式进行操作,我从那里获取了 NotifyTaskCompletion 类并删除了 INotifyPropertyChanged。我尝试使用此类获取属性的数据:Teacher _teacher => new task execution(DataWorker.Get a teacher (IdTeacher)).The result;但是结果仍然没有显示在数据网格中。
猜你喜欢
  • 2017-05-13
  • 2011-02-21
  • 1970-01-01
  • 1970-01-01
  • 2012-03-15
  • 2011-06-26
  • 2017-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多