Scrolling to a Particular Item in WrapPanel

11 posts, 0 answers
  1. Chad
    Chad avatar
    8 posts
    Member since:
    Feb 2011

    Posted 26 Feb 2011 Link to this post

    Hi,

    I'm using a RadWrapPanel as template for an ItemsControl, where the items are wrapping vertically.  I am trying to figure out a way to automatically scroll to any particular item.  I figured out I could use ScrollToHorizontalOffset, but the difficult parts for me are figuring out what "offset" means (count in pixels??), figuring out whether an item is in view or not, and what its offset is.  I'm binding an ObservableCollection of strings.  Could you point me in the right direction?

    Thanks!
  2. Deyan
    Admin
    Deyan avatar
    2039 posts

    Posted 01 Mar 2011 Link to this post

    Hi Chad,

    Thanks for contacting us and for your questions.

    The ItemsControl does not implement logic that allows scrolling to a particular item. You can use the ListBox control instead. This control has a ScrollIntoView method that accepts the object you would like to scroll to as an argument. You can still use the RadWrapPanel by setting the ItemsPanel property of the ListBox control.

    I hope this helps.

    Do not hesitate to get back to us in case you need further assistance.

    Greetings,
    Deyan
    the Telerik team
    Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
  3. DevCraft banner
  4. Chad
    Chad avatar
    8 posts
    Member since:
    Feb 2011

    Posted 08 Mar 2011 Link to this post

    Hmm, thank you but I am not getting something.

    First, if I use the RadWrapPanel as the ItemPanelTemplate for a ListBox, the controls don't actually wrap... It just appears in one long list like a standard ListBox.  is this what you meant?
    <ListBox Name=listBox1">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <telerikPrimitives:RadWrapPanel Orientation="Vertical" IsAnimated="True" />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

    Second, ScrollIntoView doesn't really seem to work. (??)  I'm binding ObservableCollection<string> MyList to the ListBox. Whether I use any of these:
    listBox1.ScrollIntoView("string");
    listBox1.ScrollIntoView(listBox1.Items[5]);
    listBox1.ScrollIntoView(listBox1.Items.IndexOf(mystring));
    listBox1.ScrollIntoView(MyList[MyList.IndexOf(mystring));
    ...it just seems to scroll back to the top every time.
  5. Deyan
    Admin
    Deyan avatar
    2039 posts

    Posted 09 Mar 2011 Link to this post

    Hi Chad,

    Thanks for getting back to me.

    Whether the controls in the RadWrapPanel will wrap or not depends on the orientation of the panel, as well as on the size of the items. For me, the scenario we are discussing works as expected. I am sending a sample Windows Phone application that demonstrates it.

    If you still continue experiencing difficulties, please prepare a sample app and send it to us so that we can take a look and handle the case properly. Please note that you will have to open a new support ticket in order to be able to attach files.

    Thanks for your time.

    Greetings,
    Deyan
    the Telerik team
    Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
  6. Chad
    Chad avatar
    8 posts
    Member since:
    Feb 2011

    Posted 10 Mar 2011 Link to this post

    Hi Deyan,

    Thanks for the sample app. I see what the difference is regarding the wrapping behavior. If you set the radWrapPanel to vertical orientation, you will see what I am seeing. I am expecting the items to reach the bottom of the panel and then wrap to the next column on the right. Scrolling should be left/right. I think this is why I originally went with an ItemsControl...but that has caused difficulty with scrolling into view... Perhaps there's a settings I'm just not seeing?

    As for the scrolling into view not working for me, I am not sure why. but it has something to do with using an ObserveableCollection and changing a value in the bound control just before issuing the ScrollIntoView request. To see it, change your code like this:

    Add: using System.Collections.ObjectModel;

    Change: List<string> items = new List<string>();
    To: ObservableCollection<string> items = new ObservableCollection<string>();

    Add two lines to Button_Click():
    items[160] = "new value";
    this.listBox.ScrollIntoView("new value");

    You will see the Scroll doesn't work at all for either "new value" or "Item 40."  This is something peculiar to the ItemsPanel/RadWrapControl, because when I comment out the ItemsPanel (using the listbox with the default panel), scrolling works.

    If you would like me to send the sample code back to you, please direct me one where to open a support ticket.

    Thank you!
  7. Deyan
    Admin
    Deyan avatar
    2039 posts

    Posted 14 Mar 2011 Link to this post

    Hello Chad,

    Thanks for writing back and for the provided details.

    I have further investigated your case using the hints you shared and was able to reproduce the behavior that you describe. I was able to find a workaround as well but before discussing it I would like to make some notes on the issue with the orientation of the RadWrapPanel when used in a ListBox. The ListBox control puts its ItemsPanel in a ScrollViewer. The ScrollViewer measures its child with infinite size so that it acquires the desired size and calculate the parameters for the scrollbars. By putting a RadWrapPanel in a ScrollViewer it gets an infinite size available for its height and thus resizes itself to fit all the items without wrapping them.

    As for the issue with the ScrollIntoView, it seems that it is related to the fact that the ListBox does not update its layout immediately after the collection change and thus the ScrollIntoView call does nothing. You can force a layout update before calling ScrollIntoView and it will work as expected. Take a look at the code snippet below:

    items[160] = "new value";
    this.listBox.UpdateLayout();
    this.listBox.ScrollIntoView("new value");

    I hope this helps.

    Do not hesitate to get back to us in case of further questions.

    All the best,
    Deyan
    the Telerik team
    Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
  8. Chad
    Chad avatar
    8 posts
    Member since:
    Feb 2011

    Posted 14 Mar 2011 Link to this post

    Thanks! Is there a way, then, when the RadWrapPanel is inside a ListBox, to make its containing ScrollViewer have a specific height (not infinity), and to make it scroll left/right instead of up/down?

    Or, back to the original post =) is there a way to scroll to a particular item when using an ItemsControl with a RadWrapPanel as the template?
  9. Deyan
    Admin
    Deyan avatar
    2039 posts

    Posted 18 Mar 2011 Link to this post

    Hi Chad,

    Thanks for getting back to me and for your questions.

    The ScrollViewer has a specific height/width. It, however, does not always measure its children with this height/width. It measures them with infinite height/width (according to its scrollbar settings) in order to be able to calculate the scrollable bounds. This behavior cannot be changed. If you wish your items to wrap, you can use the following approaches:

    1. Use the ListBox control with a RadWrapPanel with Orientation set to Horizontal. In this way the items in the control will be wrapped horizontally and you will be able to scroll in vertical manner.

    <ListBox x:Name="ListBox" FontSize="40" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Border Background="DarkGoldenrod">
                    <TextBlock Text="{Binding}" TextWrapping="Wrap"/>
                </Border>
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <telerikPrimitives:RadWrapPanel Orientation="Horizontal" >
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>


    2. Use the ListBox control  with a RadWrapPanel with Orientation property set to Vertical. You should also disable the vertical scrollbar of the ListBox and enable the horizontal by setting the corresponding attached properties of the ScrollViewer to the ListBox. In this way the RadWrapPanel will wrap its children in columns and you will be able to scroll in horizontal manner.

    <ListBox x:Name="ListBox" FontSize="40" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Auto">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Border Background="DarkGoldenrod">
                    <TextBlock Text="{Binding}" TextWrapping="Wrap"/>
                </Border>
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <telerikPrimitives:RadWrapPanel Orientation="Vertical"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>


    3. Use the ListBox control with a RadWrapPanel with Orientation set to Vertical, set MaxHeight to the RadWrapPanel. You should also enable both the vertical and horizontal scrolling in the control since the wrapped items might exceed the viewport of the listbox in horizontal direction.

    <ListBox x:Name="ListBox" FontSize="40" ScrollViewer.HorizontalScrollBarVisibility="Auto" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Border Background="DarkGoldenrod">
                    <TextBlock Text="{Binding}" TextWrapping="Wrap"/>
                </Border>
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <telerikPrimitives:RadWrapPanel Orientation="Vertical" MaxHeight="800"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

    I believe the third scenario is the closest one to what you would like to achieve.

    As for the second question, take a look at my last response where I demonstrate how to scroll to a given item using the ListBox control. The ItemsControl itself does not expose this functionality as already discussed.

    I hope this helps.

    Regards,
    Deyan
    the Telerik team
    Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
  10. Chad
    Chad avatar
    8 posts
    Member since:
    Feb 2011

    Posted 18 Mar 2011 Link to this post

    Thanks for the reply! Option 2 (or 3) seem to be pretty close to what I want. In fact, I had tried option 2 previously, but the problem was that ScrollIntoView didn't work--ack!

    I played around with option 3 and discovered that ScrollIntoView only seems to works *vertically*. That is, it only scrolls so that the vertical is within the current view. It does not scroll the horizontal at all. This is why it seemed to do nothing in option 2; because all items fit vertically within the view. In option three, when the Height of the RadWrapPanel is greater than the height of the Listbox, it does bring the correct row into view, but not the correct column.

    I'm not sure if that behavior is in my power to change.
  11. Chad
    Chad avatar
    8 posts
    Member since:
    Feb 2011

    Posted 19 Mar 2011 Link to this post

    Is there an easy way to determine the horizontal offset of the item in question within the RadWrapPanel?
  12. Deyan
    Admin
    Deyan avatar
    2039 posts

    Posted 22 Mar 2011 Link to this post

    Hi Chad,

    Thanks for getting back to me.

    Well, it seems that ScrollIntoView works only in vertical direction, at least based on my empirical estimations (and yours as well). Also, I am not quite sure that this behavior can be changed.

    As for calculating the offset of a visual item withing the RadWrapPanel, you could use the following approach:

    ListBoxItem item = this.listBox.ItemContainerGenerator.ContainerFromIndex(160) as ListBoxItem
    Point p = item.TransformToVisual(this.listBox).Transform(new Point(0, 0));

    This, for instance, will take the visual container of the 160th item in the listbox and calculate its offset from the top-left edge of the ItemsPanel (in your case the RadWrapPanel).

    I hope this helps.

    Let me know if you need further assistance on this.

    Regards,
    Deyan
    the Telerik team
    Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
Back to Top
DevCraft banner