WPF + MVVMLight + Xceed Datagrid + OData(异步)+ DataGridVirtualizingCollectionViewSource =如何?

时间:2018-10-16 14:22:00

标签: wpf asynchronous datagrid mvvm-light xceed

我有一个使用MVVMLight的WPF项目,我需要显示来自OData服务(异步请求)的文章列表。

我想使用DataGridVirtualizingCollectionViewSource进行平滑滚动。

我的Xaml:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform"

<UserControl.Resources>
    <xcdg:DataGridVirtualizingCollectionViewSource  x:Key="Articles"    

     Source="{Binding Articles}"   
     PageSize="50" 
     ItemType="{x:Type types:Article}" >

        <i:Interaction.Triggers>
            <i:EventTrigger EventName="QueryItems">
                <cmd:EventToCommand Command="{Binding Path=QueryItemsCommand}" PassEventArgsToCommand="True"  />
            </i:EventTrigger>
            <i:EventTrigger EventName="QueryItemCount">
                <cmd:EventToCommand Command="{Binding Path=QueryItemCountCommand}" PassEventArgsToCommand="True"  />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </xcdg:DataGridVirtualizingCollectionViewSource>

</UserControl.Resources>
<DockPanel LastChildFill="True" >    

    <xcdg:DataGridControl 
    x:Name="dataGrid"
    ItemsSource="{Binding Source={StaticResource Articles}}"
         >
        <xcdg:DataGridControl.View>
            <xcdg:TableflowView UseDefaultHeadersFooters="False">
                <xcdg:TableflowView.FixedHeaders>
                    <DataTemplate>
                        <xcdg:ColumnManagerRow />
                    </DataTemplate>
                </xcdg:TableflowView.FixedHeaders>
            </xcdg:TableflowView>
        </xcdg:DataGridControl.View>
    </xcdg:DataGridControl>
</DockPanel>

我的ViewModel

public async Task QueryItems(QueryItemsEventArgs e)
    {
        var list = await myService.Articles.GetsAsync(top, e.AsyncQueryInfo.StartIndex);

        e.AsyncQueryInfo.EndQuery(list.ToArray());
    }

    public async Task QueryItemCount(QueryItemCountEventArgs e)
    {
        e.Count = await myService.Articles.CountAsync();   
    }



    private ICommand queryItemsCommand;
    public ICommand QueryItemsCommand
    {
        get
        {
            return queryItemsCommand ?? (queryItemsCommand = new AsyncRelayCommand<QueryItemsEventArgs>(QueryItems));
        }
    }
    private ICommand queryItemCountCommand;
    public ICommand QueryItemCountCommand
    {
        get
        {
            return queryItemCountCommand ?? (queryItemCountCommand = new AsyncRelayCommand<QueryItemCountEventArgs>(QueryItemCount));
        }
    }



    private ObservableCollection<Article> articles = new ObservableCollection<Article>();
    public ObservableCollection<Article> Articles { get { return articles; } set { Set(ref articles, value); } }

AsyncRelayCommand.cs

public class AsyncRelayCommand<T> : ICommand
{
    private readonly Func<T, Task> execute;
    private readonly Func<T, bool> canExecute;

    private long isExecuting;

    public AsyncRelayCommand(Func<T, Task> execute, Func<T, bool> canExecute = null)
    {
        this.execute = execute;
        this.canExecute = canExecute ?? (o => true);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void RaiseCanExecuteChanged()
    {
        CommandManager.InvalidateRequerySuggested();
    }

    public bool CanExecute(object parameter)
    {
        if (Interlocked.Read(ref isExecuting) != 0)
            return false;

        return canExecute((T)parameter);
    }

    public async void Execute(object parameter)
    {
        Interlocked.Exchange(ref isExecuting, 1);
        RaiseCanExecuteChanged();

        try
        {
            await execute((T)parameter);
        }
        finally
        {
            Interlocked.Exchange(ref isExecuting, 0);
            RaiseCanExecuteChanged();
        }
    }
}

当我尝试此代码时,将正确触发QueryItemCount,e.Count异步获取计数,并且方法按预期完成。 但是在那之后,永远不会触发QueryItems!

当我强制刷新数据网格时,该计数被调用,但是该计数为-1,就像我从未设置过:(

我尝试了很多事情(Task.Run,​​.Result,UI线程上的调度等),但没有任何效果。 我需要一些新想法。 谢谢

0 个答案:

没有答案