繁体   English   中英

将 DataTable 加载到 WPF DataGrid MVVM

[英]Load DataTable to WPF DataGrid MVVM

一段时间以来,我一直试图将我的项目移至 MVVM。

我从数据库中获取了一个数据表:

MainProcess.cs:

    public static DataTable CustomersInLiinos = new DataTable();

    public static void MergedTable()
    {
        var t1 = ConnectAndRetriveDatatatableS(); // t1
        var t2 = ConnectAndRetriveDatatatableF(); // t2

        CustomersInLiinos = t1.Copy();
        CustomersInLiinos.Merge(t2);
    }

视图模型.cs:

    private async Task ExecuteLoadMainTableDataAsync(object commandParameter)
    {
        if (MainProcess.CheckForVPNInterface())
        {
            if (MainProcess.CustomersInLiinos != null)
            {
                this.HasProgress = true;

                IEnumerable<Item> resultItems = await LoadMainTableDataAsync();
                this.Items = new ObservableCollection<Item>(resultItems);
                EnableItemsFiltering();

                this.HasProgress = false;
            }
        }
        else
        {
            throw new VpnInterfaceException("Please, check your VPN connection!");
        }
    }

在 ViewModel.cs 里面我也有这个:

    public Task<DataView> LoadMainTableDataAsync()
    {
        return Task.Run(() =>
        {
            MainProcess.MergedTable();

            return MainProcess.CustomersInLiinos.DefaultView;
        });
    }

目前我有一个错误指向await LoadMainTableDataAsync();

严重性代码描述项目文件行抑制状态错误 CS0266 无法将类型“System.Data.DataView”隐式转换为“System.Collections.Generic.IEnumerable<Liinos_inspector_FilterTest.Item>”。 存在显式转换(您是否缺少演员表?)

我了解LoadMainTableDataAsync中存在错误? 我正在将数据加载到 DataView,应该加载到 IEnumerable 吗?

使用这个会更容易吗:

    public class JoinedFandS
    {
       public string YRNRO { get; set; }
       public string HAKUNIMI { get; set; }
       public string NIMIA { get; set; }
       public string NIMIB { get; set; }
    }

    public static IEnumerable<JoinedFandS> GetMyJoinedResult()
    {
        var t1 = ConnectAndRetriveDatatatableS(); // t1
        var t2 = ConnectAndRetriveDatatatableF(); // t2

        var firstTable = ...

        var secondTable = ...

        var results = firstTable.Concat(secondTable);

        return results;
    }

编辑:

<Window x:Class="Liinos_inspector_FilterTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:Liinos_inspector_FilterTest="clr-namespace:Liinos_inspector_FilterTest" 
        mc:Ignorable="d"
        Title="Liinos database inspector" Height="672" Width="1000" Icon="Images/logo_icon-small.jpg" Background="White" MinWidth="1000">

  <Window.DataContext>
    <ViewModel />
  </Window.DataContext>

严重性代码描述项目文件行抑制状态错误 XLS0414 未找到类型“ViewModel”。 验证您没有缺少程序集引用并且所有引用的程序集都已构建。 Liinos 检查器 FilterTest MainWindow.xaml 11

严重性代码说明项目文件行抑制状态错误 XDG0008 Windows Presentation Foundation (WPF) 项目不支持 ViewModel。 Liinos 检查器 FilterTest MainWindow.xaml 11

我应该使用什么来代替 ViewModel?

这是数据类型不匹配。 您不能将DataView压入集合中。 存储DataTable而不是DataView也更实用。 从表中获取视图比从视图中获取表更便宜(以防您稍后需要对DataTable进行操作)。
修复此错误还需要修复过滤。

DataGrid可以直接处理DataTable

请注意,您必须await LoadMainTableDataAsync的返回值。 否则这个方法会过早返回(因为结果是在后台线程中计算的)。 我敢肯定,这部分代码甚至无法编译。 也许这只是示例代码。

此示例还根据新的数据结构调整过滤。 要过滤DataTable.DataView您必须使用DataView.RowFilter属性(请参阅表达式语法以获取帮助)。 您需要根据您的要求调整实际的过滤器逻辑:

视图模型.cs

class ViewModel : INotifyPropertyChanged
{
  public ICommand LoadMainTableDataCommand => new RelayCommand(async param => ExecuteLoadMainTableDataAsync());

  private DataTable mainDataTable;   
  public DataTable MainDataTable 
  {
    get => this.mainDataTable;
    set 
    { 
      this.mainDataTable = value; 
      OnPropertyChanged();  
      
      // Set the DataTable filter expression
      EnableRowFiltering();
    }
  }

  // Binding source for the first name TextBox
  private string firstNameSearchKey;   
  public string FirstNameSearchKey
  {
    get => this.firstNameSearchKey;
    set 
    { 
      this.firstNameSearchKey = value; 
      OnPropertyChanged();  
      
      // Refresh the DataTable filter expression
      EnableRowFiltering();
    }
  }

  // Binding source for the last name TextBox
  private string lastNameSearchKey;   
  public string LastNameSearchKey
  {
    get => this.lastNameSearchKey;
    set 
    { 
      this.lastNameSearchKey = value; 
      OnPropertyChanged();  
      
      // Refresh the DataTable filter expression
      EnableRowFiltering();
    }
  }

  private bool hasProgress;   
  public bool HasProgress
  {
    get => this.hasProgress;
    set 
    { 
      this.hasProgress = value; 
      OnPropertyChanged();
    }
  }

  public void EnableRowFiltering()
  {
    // The filter assumes a column 'FirstName' and a column 'LastName' in the DataView. 
    // The filter expression mimics string.StartsWith.
    this.MainDataTable.DefaultView.RowFilter = 
      $"FirstName LIKE '{this.FirstNameSearchKey}*' " + 
      $"OR LastName LIKE '{this.LastNameSearchKey}*'";
  }

  private async Task ExecuteLoadMainTableDataAsync()
  {
    if (MainProcess.CheckForVPNInterface())
    {
      if (MainProcess.Customers != null)
      {
        this.HasProgress = true;

        this.MainDataTable = await LoadMainTableDataAsync();

        this.HasProgress = false;
      }
    }
    else
    {
      throw new VpnInterfaceException("Please, check your VPN connection!");
    }
  } 

  public async Task<DataTable> LoadMainTableDataAsync()
  {
    return await Task.Run(() =>
    {
      MainProcess.MergedTable();

      return MainProcess.CustomersInLiinos;
    });
  }

  public event PropertyChangedEventHandler PropertyChanged;
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

主窗口.xaml

<Window>
  <Window.DataContext>
    <ViewModel />
  </Window.DataContext>

  <Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
  </Window.Resources>
 
  <StackPanel>
    <ProgressBar IsIndeterminate="True"
                 Visibility="{Binding HasProgress, Converter={StaticResource BooleanToVisibilityConverter}}" />

    <Button Command="{Binding LoadMainTableDataCommand}" 
            Content="Load Data" />

    <TextBox Text="{Binding FirstNameSearchKey}" />
    <TextBox Text="{Binding LastNameSearchKey}" />
    <DataGrid ItemsSource="{Binding MainDataTable}" />
  <StackPanel>
</Window>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM