2011-01-25 2 views
2

У меня есть свод, чей ItemSource установлен в набор объектов данных, и я использую ItemTemplate для преобразования элементов в содержимое пользовательского интерфейса (я также использую HeaderTemplate).WP7: Получить текущий PivotItem для привязанных к данным Pivot

При сборке я обычно получаю ScrollViewer из текущего PivotItem и сохраняю текущую позицию, чтобы я мог вернуться назад в нужную позицию, если пользователь перейдет обратно в мое приложение. Это отлично работает, если я жестко программирую PivotItems в своем XAML.

Проблема заключается в том, что когда Pivot привязан к моей коллекции объектов данных с помощью ItemsSource, SelectedItem возвращает один из моих объектов данных - не PivotItem. Я не вижу, как добраться до текущего PivotItem (или элементов пользовательского интерфейса, созданных с помощью ItemTemplate). Я заметил, что защищенные члены перешли от элемента ItemsSource к соответствующему контейнеру - возможно, мне нужно извлечь из Pivot, чтобы использовать их?

Спасибо!

Damian

ответ

4

Другой способ, чтобы получить элемент Pivot описан здесь - http://bea.stollnitz.com/blog/?p=7

Получить referenec к управлению Pivot, а затем вы можете использовать Pivot.ItemContainerGenerator.ContainerFromIndex (индекс) ф ​​получить PivotItem или вы можете использовать Pivot. ItemContainerGenerator.ContainerFromItem (dataobject)

+0

Гораздо более элегантный - спасибо за этот совет. – Damian

+0

Pivot.ItemContainerGenerator.ContainerFromIndex (0) возвращает null для меня по какой-то странной причине ... – TDaver

1

Почему бы не использовать свойство SelectedIndex?

+0

Это работает, когда вы указываете PivotItems в своем XAML, но если вы привязываете ItemsSource к коллекции данных, то коллекция Items содержит ваши объекты данных, а не PivotItems. – Damian

2

Если по какой-то причине вам нужны фактические текущие PivotItem, а не данные, связанные с этим, тогда я думаю, вам нужно будет пересечь визуальное дерево, чтобы найти его. Я использую следующие методы, чтобы помочь в этом:

 /// <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); 
      } 
     }

Таким образом, вы будете использовать это следующим образом:

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

Это выглядит великолепно - я не думал, чтобы ходить по визуальному дереву, чтобы найти объект, данные которого соответствуют выбранному элементу. – Damian

+0

Когда я его запустил, он не совсем сработал - PivotItems не являются младшими детьми уровня Pivot в визуальном дереве. Я опубликовал уточнение вашего предложения в качестве отдельного ответа - большое спасибо за то, что указал мне в правильном направлении. [Как, в стороне, я думаю, вы использовали Select вместо Where, хотя вы могли бы поместить фильтр в FirstOrDefault - .GetVisualChildren(). FirstOrDefault (p => p.DataContext == this._pivot.SelectedItem)] – Damian

+0

-1, потому что, хотя это вообще правильно, вы должны заметить, что с самого начала WPF ItemsControl имеет свойство ItemContainerGenerator, которое должно использоваться исключительно для dataitem <-> logicalindex <-> visualitem отображение !! – quetzalcoatl

3

Я upvoted ответ Дерека, поскольку он послал меня в правильном направлении. Метод расширения он предложил только пошел на один уровень глубоко, поэтому я придумал следующий рекурсивный метод расширения, который работает для меня:

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; 
} 

И тогда я использую его следующим образом:

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

Этот подход - всего лишь изысканность Дерека - все его честь.

+1

Я считаю, что целую кучу таких методов расширения можно найти в наборе инструментов Silverlight, и если я правильно помню, они работают как обаяние под WP7. И это не только Find-Child или Find-Ancestor. Я также видел некоторые проекты, связанные с linq-to-visual-tree sibling, которые вы можете проверить! – quetzalcoatl

Смежные вопросы