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

Filtering RadLoopingList with ObservableCollection

8 Answers 132 Views
LoopingList
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Pol
Top achievements
Rank 1
Pol asked on 31 Mar 2011, 07:57 AM
Hello
Is it possible to bind RadLoopingList to ObservableCollection? I want to provide filtering with ICollectionView.Filter.
If not, what is preffered method to provide filtering for RadLoopingList?

Best regards
Pol

8 Answers, 1 is accepted

Sort by
0
Accepted
Georgi
Telerik team
answered on 04 Apr 2011, 02:40 PM
Hello Pol,

Thank you for your question.

RadLoopingList does not behave like a standard ListBox. It uses completely different approach for visualizing its items and does not rely on pre-created data items.

Generally you will need to follow these steps in order to properly setup the control:

- Handle the ItemNeeded event of LoopingListDataSource and provide an instance of your business object.
- Handle the ItemUpdated event of LoopingListDataSource and set the desired properties of the associated business object, depending on the provided logical index. Note that your business object should raise the LoopingListDataItem.OnPropertyChanged with the correct property name so that the item is visually updated.
- And of course you will need the appropriate DataTemplate applied to the RadLoopingList.ItemTemplate property.

More information about the control may be found in our documentation and in our demo application (part of the installation package) - there are two examples that showcase control's usage.

So, the filtering should happen when preparing the item to be visualized - either in the ItemNeeded or in the ItemUpdated event.

I hope this helps. Let me know if you have other questions.

All the best,
Georgi
the Telerik team
Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
0
Kate
Top achievements
Rank 1
answered on 18 May 2012, 04:26 PM
Can you explain more about raising the LoopingListDataItem.OnPropertyChanged event?  I can't find a good, simple example anywhere of how to update the control properly.  When I have more items in my list than can be displayed at a time on the page and scroll to see the bottom items, instead of showing the updated contents I see repeats of the initial items.

i.e. in a list of 0 - 10 items, the 9th and 10th items will instead show the 0th and 1st items.
0
Deyan
Telerik team
answered on 19 May 2012, 07:13 AM
Hi Kate,

Thanks for writing and for your question.

You can read more about the INotifyPropertyChanged interface here:

http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

In a nutshell, this interface allows you to raise an event when a property on your business object changes thus informing the subscribers that they should refresh their state. This is a well know .NET interface that many native components use to receive notifications of updates that happen on objects created by you as a developer.

Please let me know if you need further assistance here.

All the best,
Deyan
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Kate
Top achievements
Rank 1
answered on 21 May 2012, 03:53 PM
Thanks Deyan,

How does that work with the item_updated and item_needed model described in the tool section for radloopinglist here?

For example, I am populating the radloopinglist with directions data (ItineraryData) as follows:

public class ItineraryData : ObservableCollection<string>
{       
    private static LoopingListDataSource src;
    private IEnumerator<BingRouteService.ItineraryItem> itineraryListEnumerator;
 
    public ItineraryData(ObservableCollection<BingRouteService.ItineraryItem> itineraryList)
    {
        src = new LoopingListDataSource(itineraryList.Count);
        itineraryListEnumerator = itineraryList.GetEnumerator();
 
        src.ItemNeeded += (sender, args) =>
        {
            if (itineraryListEnumerator.MoveNext())
            {
                DirectionsPanel dp = new DirectionsPanel();
                dp.distanceInfo = itineraryListEnumerator.Current.Summary.Distance.ToString() + " mi";
                dp.directionsText = parseXML(itineraryListEnumerator.Current.Text);
                dp.itemNumber = args.Index.ToString();
                args.Item = new DirectionsPanel() { distanceInfo = dp.distanceInfo };
                args.Item = new DirectionsPanel() { directionsText = dp.directionsText };
                args.Item = new DirectionsPanel() { itemNumber = dp.itemNumber };
            }
        };
 
        src.ItemUpdated += (sender, args) =>
        {
            DirectionsPanel dp = new DirectionsPanel();
            dp.distanceInfo = itineraryListEnumerator.Current.Summary.Distance.ToString() + " mi";
            dp.directionsText = parseXML(itineraryListEnumerator.Current.Text);
            dp.itemNumber = args.Index.ToString();
            (args.Item as DirectionsPanel).distanceInfo = dp.distanceInfo;
            (args.Item as DirectionsPanel).directionsText = dp.directionsText;
            (args.Item as DirectionsPanel).itemNumber = dp.itemNumber;
        };
    }
 
    public LoopingListDataSource ItineraryDataSource
    {
        get
        {
            return src;
        }
    }

I tried calling "Changed()" from the get on ItineraryDataSource but I ended up with an empty control when I ran it.

Thanks for your help,
Kate
0
Deyan
Telerik team
answered on 22 May 2012, 09:24 AM
Hi Kate,

The ItemNeeded and ItemUpdated events are fired by the UI virtualization mechanism when new visual items are realized and bound to data items. The ItemNeeded event is fired when a visual container is created and inserted into the viewport as long as the viewport has space to accommodate visual items. The ItemUpdated event is then fired each time a new data item is about to be realized and positioned into the viewport. In this event you receive information about the needed data index and are supposed to update the visual container with the corresponding information.

Based on the source code that you are pasting I see that you are not correctly using these events, and the ItemNeeded event in particular. Take a look at the following snippet from your code:

args.Item = new DirectionsPanel() { distanceInfo = dp.distanceInfo };
args.Item = new DirectionsPanel() { directionsText = dp.directionsText };
args.Item = new DirectionsPanel() { itemNumber = dp.itemNumber };

Here you set the same property three times with different objects. This makes no sense, as the last value that will be valid is the last DirectionsPanel instance which overrites the previous, which correspondingly overwrites the first one.

I guess you want to make the following statement:
args.Item = new DirectionsPanel() { distanceInfo = dp.distanceInfo, itemNumber = dp.itemNumber, directionsText = dp.directionsText  };

Another problem that might be the reason for you not getting the desired behavior in RadLoopingList is, as already mentioned, the lack of the INotifyPropertyChanged support on your data objects. This will make it impossible for RadLoopingList to understand that you update the properties of your data items in the ItemUpdated event. You need to implement this interface and fire the PropertyChanged event when you set new values to your properties in order to get this working.

This article on MSDN gives great hints on how to do this:

http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

I hope this is helpful.

Kind regards,
Deyan
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Kate
Top achievements
Rank 1
answered on 23 May 2012, 06:33 AM
Hi Deyan,

This was helpful and things have improved.  I am no longer getting the first several items repeated at the end of the list, rather the 9th item (because it is the first item off the page) is repeated for as many other items are not initially rendered.

I think there is still something wrong with the way I am getting the enumerator for the list:

src.ItemNeeded += (sender, args) =>
{
    if (itineraryListEnumerator.MoveNext())
    {
        moved = true;
        DirectionsPanel dp = new DirectionsPanel();
        dp.distanceInfo = itineraryListEnumerator.Current.Summary.Distance.ToString() + " mi";
        dp.directionsText = parseXML(itineraryListEnumerator.Current.Text);
        dp.itemNumber = args.Index.ToString();
        args.Item = new DirectionsPanel() { distanceInfo = dp.distanceInfo, itemNumber = dp.itemNumber, directionsText = dp.directionsText };
    }
};

So you can see I am moving the enumerator forward when a new item is needed.  However I am not doing that if an item is updated.  I can add that logic in, but this doesn't solve the problem of when the user scrolls upward.  Do I really have to handle all this myself or is there a simpler way?

Thanks for your help!
Kate
0
Kate
Top achievements
Rank 1
answered on 23 May 2012, 07:05 AM
Nevermind, I think I've got it!  I used the args.Index to figure out which item I need in the list:

            src.ItemNeeded += (sender, args) =>
            {
                itineraryListEnumerator.Reset();
                for (int i = 0; i <= args.Index; i++)
                {
                    itineraryListEnumerator.MoveNext();
                    moved = true;
                }
                DirectionsPanel dp = new DirectionsPanel();
                dp.distanceInfo = itineraryListEnumerator.Current.Summary.Distance.ToString() + " mi";
                dp.directionsText = parseXML(itineraryListEnumerator.Current.Text);
                dp.itemNumber = args.Index.ToString();
                args.Item = new DirectionsPanel() { distanceInfo = dp.distanceInfo, itemNumber = dp.itemNumber, directionsText = dp.directionsText };
            };
 
            src.ItemUpdated += (sender, args) =>
            {
                if (moved == false)
                {
                    itineraryListEnumerator.Reset();
                    for (int i = 0; i <= args.Index; i++)
                    {
                        itineraryListEnumerator.MoveNext();
                        moved = true;
                    }
                }
                DirectionsPanel dp = new DirectionsPanel();
                dp.distanceInfo = itineraryListEnumerator.Current.Summary.Distance.ToString() + " mi";
                dp.directionsText = parseXML(itineraryListEnumerator.Current.Text);
                dp.itemNumber = args.Index.ToString();
                (args.Item as DirectionsPanel).distanceInfo = dp.distanceInfo;
                (args.Item as DirectionsPanel).directionsText = dp.directionsText;
                (args.Item as DirectionsPanel).itemNumber = dp.itemNumber;
                moved = false;
            };
0
Deyan
Telerik team
answered on 23 May 2012, 11:12 AM
Hi Kate,

Great that you've managed to handle the case.

Let us know as soon as you have further questions or need assistance.

Greetings,
Deyan
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Tags
LoopingList
Asked by
Pol
Top achievements
Rank 1
Answers by
Georgi
Telerik team
Kate
Top achievements
Rank 1
Deyan
Telerik team
Share this question
or