This is a migrated thread and some comments may be shown as answers.

Load VirtualQueryableCollectionView items based on ID instead of index

1 Answer 51 Views
Data Virtualization
This is a migrated thread and some comments may be shown as answers.
Pieter
Top achievements
Rank 1
Pieter asked on 13 Nov 2013, 12:46 PM
We are using the RadGridView with a VirtualQueryableCollectionView as Itemsource using WPF and EF. 
This works great for paging and scrolling, however we can't figure out how to deal with the following situation:

- We sort the grid by a property, name for instance. 
- Then, outside of the grid, the name property is altered
- Our viewmodel receives a message that the item has changed

What we want to do now, is to refresh the grid, with the current item still selected.
However, since the name has changed, we don't know the index that has to be queried to get the item with the id of the changed item.

So the question is: knowing the ID of an entity, how can you make VirtualQueryableCollectionView load the item with that ID into the grid?The same situation arises when we want to select a entity (with known id) that has been newly created outside of the viewmodel.


We use the following VirtualQueryableCollectionViewHelper to create the set the VirtualQueryableCollecitonView.

 QueryGenerator(QueryableXenoxContext) returns an EntityQuery


public class VirtualQueryableCollectionViewHelper<T> where T : Entity
{
    public IEventAggregator EventAggregator { get; set; }
    public VirtualQueryableCollectionViewHelper(Func<QueryableXenoxContext, EntityQuery<T>> queryGenerator, queryableXenoxContext queryableXenoxContext, XenoxGridView gridView)
    {
        EventAggregator = ClientIocContainer.Instance.GetExportedValue<IEventAggregator>();
        QueryGenerator = queryGenerator;
        QueryableXenoxContext = queryableXenoxContext;
        GridviewControl = gridView;
        DoNothing = i => { };
 
        View = new VirtualQueryableCollectionView<T>
        {
            LoadSize = 30,
            VirtualItemCount = 100
        };
 
        View.ItemsLoading += (sender, args) => LoadInternal(args.StartIndex, args.ItemCount, DoNothing);
 
 
        View.FilterDescriptors.CollectionChanged += (sender, args) => LoadInternal(0, View.LoadSize, DoNothing);
        View.FilterDescriptors.ItemChanged += (sender, args) => LoadInternal(0, View.LoadSize, DoNothing);
        View.SortDescriptors.CollectionChanged += (sender, args) => LoadInternal(0, View.LoadSize, DoNothing);
 
        if (gridView == null)
        {
            ScrollIndexIntoView = DoNothing;
        }
        else
        {
            ScrollIndexIntoView = i => gridView.ScrollIndexIntoCenterOfView(i);
        }
    }
     
    public void Load(int currentIndex, int pageSize)
    {
        LoadInternal(currentIndex, pageSize, ScrollIndexIntoView);
    }
 
 
    public void Refresh(bool scrollToIndex = false, int currentIndex = 0)
    {
        var postLoadAction = scrollToIndex ? ScrollIndexIntoView : DoNothing;
        LoadInternal(currentIndex, View.LoadSize, postLoadAction);
    }
 
    public IEnumerable<T> GetAllCollectionItems()
    {
        return QueryableXenoxContext.Load(QueryGenerator(QueryableXenoxContext)).Entities;
    }
 
    private void LoadInternal(int currentIndex, int pageSize, Action<int> onLoaded)
    {
        if (currentIndex < 0) currentIndex = 0;
        //also load content above current item
        pageSize = pageSize*2;
        var loadStartIndex = currentIndex - pageSize / 2 < 0 ? 0 : currentIndex - pageSize / 2;
 
        var entityQuery =
            QueryGenerator(QueryableXenoxContext)
                .Sort(View.SortDescriptors)
                .Where(View.FilterDescriptors)
                .Skip(loadStartIndex)
                .Take(pageSize);
 
        entityQuery.IncludeTotalCount = true;
 
        try
        {
            QueryableXenoxContext.Load(entityQuery, LoadBehavior.RefreshCurrent, lo => {
                if (lo.TotalEntityCount != -1 && lo.TotalEntityCount != View.VirtualItemCount) {
                    View.VirtualItemCount = lo.TotalEntityCount;
                }
 
                View.Load(loadStartIndex, lo.Entities);
 
                onLoaded(currentIndex);
            }, null);
        }
        catch (InvalidOperationException)
        {
            EventAggregator.Publish(new ErrorReportedEvent("Error loading items. Possible cause: too many items selected"));
        }
    }

1 Answer, 1 is accepted

Sort by
0
Dimitrina
Telerik team
answered on 18 Nov 2013, 12:02 PM
Hello,

Generally our virtual collection is designed to serve mostly read-only scenarios. If you want to add/remove items you can do this in the source of the virtual collection but you will have to reload the collection if/when needed. This is how the VirtualQueryableCollectionView works. 

In your case, you can call the ResetItems(startIndex, count) method to reload a particular item. I am afraid that this can only be done by index.

Regards,
Didie
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
Tags
Data Virtualization
Asked by
Pieter
Top achievements
Rank 1
Answers by
Dimitrina
Telerik team
Share this question
or