开发者

WP7: Get current PivotItem for data-bound Pivot

I have a Pivot, whose ItemsSource is set to a collection of data objects, and I use an ItemTemplate to transform the items into UI content (I also use a HeaderTemplate).

When tombstoning, I normally get the ScrollViewer from the current PivotItem and save the current position away, so that I can scroll back to the right position if the user nav开发者_StackOverflowigates back to my app. This works fine if I hard-code the PivotItems in my XAML.

My issue is that the when the Pivot is bound to my data object collection using ItemsSource, SelectedItem returns one of my data objects - not the PivotItem. I can't see how to get to the current PivotItem (or the UI elements generated from my ItemTemplate). I've noticed protected members to go from a ItemsSource item to its corresponding container - perhaps I need to derive from Pivot to make use of these?

Thanks!

Damian


Another way to get the Pivot item is described here - http://bea.stollnitz.com/blog/?p=7

Get a referenec to the Pivot control and you can then use Pivot.ItemContainerGenerator.ContainerFromIndex(index) tp get the PivotItem or you can use Pivot.ItemContainerGenerator.ContainerFromItem(dataobject)


I've upvoted Derek's answer since it sent me in the right direction. The extension method he suggested only went one level deep though, so I've come up with the following recursive extension method which works for me:

internal static T FindVisualChild<T>(this DependencyObject parent,
                                    Func<T, bool> filter)
                                    where T : DependencyObject
{
    var childCount = VisualTreeHelper.GetChildrenCount(parent);
    for (var i = 0; i < childCount; i++)
    {
        var elt = VisualTreeHelper.GetChild(parent, i);
        if (elt is T && filter((T)elt)) return (T)elt;
        var result = FindVisualChild(elt, filter);
        if (result != null) return result;
    }
    return null;
}

And then I use it as follows:

var item = pivot.FindVisualChild<PivotItem>(
                          elt => elt.DataContext == pivot.SelectedItem);

This approach is just a refinement of Derek's -- all kudos to him.


If, for some reason, you need the actual current PivotItem and not the data that is associated with it, then I think you'll need to traverse the visual tree to find it. I use the following methods to help in this:

        /// <summary>
        /// Gets the visual children of type T.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="target"></param>
        /// <returns></returns>
        public static IEnumerable<T> GetVisualChildren<T>(this DependencyObject target)
            where T : DependencyObject
        {
            return GetVisualChildren(target).Where(child => child is T).Cast<T>();
        }


        /// <summary>
        /// Get the visual tree children of an element.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns>The visual tree children of an element.</returns>
        /// <exception cref="T:System.ArgumentNullException">
        /// <paramref name="element"/> is null.
        /// </exception>
        public static IEnumerable<DependencyObject> GetVisualChildren(this DependencyObject element)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }

            return GetVisualChildrenAndSelfIterator(element).Skip(1);
        }

        /// <summary>
        /// Get the visual tree children of an element and the element itself.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns>
        /// The visual tree children of an element and the element itself.
        /// </returns>
        private static IEnumerable<DependencyObject> GetVisualChildrenAndSelfIterator(this DependencyObject element)
        {
            Debug.Assert(element != null, "element should not be null!");

            yield return element;

            int count = VisualTreeHelper.GetChildrenCount(element);
            for (int i = 0; i < count; i++)
            {
                yield return VisualTreeHelper.GetChild(element, i);
            }
        }

So you would use this as follows:

var selectedPivotItem = this._pivot
    .GetVisualChildren()
    .Select(p => p.DataContext == this._pivot.SelectedItem)
    .FirstOrDefault();


Why not use the SelectedIndex property?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜