WPF + MVVMLight + Xceed Datagrid + OData (async) + DataGridVirtualizingCollectionViewSource = Как? - PullRequest
0 голосов
/ 16 октября 2018

У меня есть проект WPF с использованием MVVMLight, мне нужно показать список статей из службы OData (асинхронный запрос).

Я хочу использовать DataGridVirtualizingCollectionViewSource для плавной прокрутки.

My 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>

My 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, Dispatch в потоке пользовательского интерфейса и т. Д.), Но ничего не получается. Мне нужны новые идеи .... Спасибо

...