/// <summary> /// When overridden in a derived class, returns a <see cref="T:System.Windows.DataTemplate" /> based on custom logic. /// </summary> /// <param name="item">The data object for which to select the template.</param> /// <param name="container">The data-bound object.</param> /// <returns> /// Returns a <see cref="T:System.Windows.DataTemplate" /> or null. The default value is null. /// </returns> public override DataTemplate SelectTemplate(object item, DependencyObject container) { if ((item == null) || (container == null)) return null; var frameworkElement = container.AncestorsAndSelf().OfType<FrameworkElement>().FirstOrDefault(); if (frameworkElement == null) return null; var key = DataTemplateManager.CreateKey(item.GetType(), Role); return (frameworkElement.TryFindResource(key) as DataTemplate) ?? FallbackValue; }
/// <summary> /// Returns a collection containing this element and all ancestor elements /// which match the given type. /// </summary> public static IEnumerable <DependencyObject> AncestorsAndSelf <T>(this DependencyObject item) { return(item.AncestorsAndSelf().Where(i => i is T)); }
/// <summary> /// Invoked when the HorizontalOffset attached property changes /// </summary> private static void OnHorizontalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ScrollViewer sv = d.AncestorsAndSelf<ScrollViewer>().FirstOrDefault() as ScrollViewer; if (sv == null) return; // check whether we have a reference to the vertical scrollbar if (sv.GetValue(horizontalScrollBarProperty) == null) { // if not, handle LayoutUpdated, which will be invoked after the // template is applied and extract the scrollbar sv.LayoutUpdated += (s, ev) => { if (sv.GetValue(horizontalScrollBarProperty) == null) { GetScrollBarsForScrollViewer(sv); } }; } else { // update the scrollviewer offset sv.ScrollToHorizontalOffset((double)e.NewValue); } }