/// <summary> /// This is an helper function to overcome the restriction on WPF framework to have /// hetrogenious hierarchy ItemsControl. The problem is an ItemsControl in it's /// internal logic fetches Item related properties from it's parent if that is an ItemsControl. /// That approach can only be successful only in homogenous hierarchy of controls from first layer /// as in case of TreeViewItem. /// /// In Ribbon control it is not true at various places and most common example could RibbonGalleryCategory. /// RibbonGalleryCategory's parent is RibbonGallery which is an ItemsControl and hence the above explained /// fetch happens. But the property specified on RibbonGallery are applicable to RibbonGalleryCategory only. /// Now, RibbonGalleryCategory's Item are not RibbonGalleryCategory but RibbonGalleryItem and hence a conflict. /// /// This function gets called from PrepareContainerOverride after the base.PrepareContainerOverride is being called /// and if the properties being fetched from the parent (changed) it sets them back to original values passed as arguments. /// </summary> /// <param name="itemsControl"> current ItemsControl</param> /// <param name="itemTemplate"></param> /// <param name="itemTemplateSelector"></param> /// <param name="itemStringFormat"></param> /// <param name="itemContainerStyle"></param> /// <param name="itemContainerStyleSelector"></param> /// <param name="alternationCount"></param> /// <param name="itemBindingGroup"></param> public static void IgnoreDPInheritedFromParentItemsControl( ItemsControl itemsControl, ItemsControl parentItemsControl, ValueAndValueSource itemTemplate, ValueAndValueSource itemTemplateSelector, ValueAndValueSource itemStringFormat, ValueAndValueSource itemContainerStyle, ValueAndValueSource itemContainerStyleSelector, ValueAndValueSource alternationCount, ValueAndValueSource itemBindingGroup, ValueAndValueSource headerTemplate, ValueAndValueSource headerTemplateSelector, ValueAndValueSource headerStringFormat) { // HeaderedItemsControl needs special consideration as some of the properties needs to be kept as is // if HierarichalDataTemplate is used. The reason is internal method PrepareHeirarchy() in HeaderedItemsControl // fetches appropriate values from the template and updates the one assigned using parentItemsControl and // those values should be kept for master-detail scenarios to be working correctly. HeaderedItemsControl hic = itemsControl as HeaderedItemsControl; HierarchicalDataTemplate hTemplate = hic != null ? hic.HeaderTemplate as HierarchicalDataTemplate : null; if (itemsControl.ItemTemplate == parentItemsControl.ItemTemplate) { if (hTemplate == null || (hTemplate.ItemTemplate == null && string.IsNullOrEmpty(hTemplate.ItemStringFormat) && hTemplate.ItemTemplateSelector == null)) { RestoreValue(itemsControl, ItemsControl.ItemTemplateProperty, itemTemplate); } } if (itemsControl.ItemTemplateSelector == parentItemsControl.ItemTemplateSelector) { if (hTemplate == null || (string.IsNullOrEmpty(hTemplate.ItemStringFormat) && hTemplate.ItemTemplateSelector == null)) { RestoreValue(itemsControl, ItemsControl.ItemTemplateSelectorProperty, itemTemplateSelector); } } if (itemsControl.ItemStringFormat == parentItemsControl.ItemStringFormat) { if (hTemplate == null || string.IsNullOrEmpty(hTemplate.ItemStringFormat)) { RestoreValue(itemsControl, ItemsControl.ItemStringFormatProperty, itemStringFormat); } } if (itemsControl.ItemContainerStyle == parentItemsControl.ItemContainerStyle) { if (hTemplate == null || (hTemplate.ItemContainerStyleSelector == null && hTemplate.ItemContainerStyle == null)) { RestoreValue(itemsControl, ItemsControl.ItemContainerStyleProperty, itemContainerStyle); } } if (itemsControl.ItemContainerStyleSelector == parentItemsControl.ItemContainerStyleSelector) { if (hTemplate == null || hTemplate.ItemContainerStyleSelector == null) { RestoreValue(itemsControl, ItemsControl.ItemContainerStyleSelectorProperty, itemContainerStyleSelector); } } if (itemsControl.AlternationCount == parentItemsControl.AlternationCount) { // Potential issue if 0 is set intentionally, but one can argue if it is explicitly defined on // ItemsControl itself then use that one. if (hTemplate == null || hTemplate.AlternationCount == 0) { RestoreValue(itemsControl, ItemsControl.AlternationCountProperty, alternationCount); } } if (itemsControl.ItemBindingGroup == parentItemsControl.ItemBindingGroup) { if (hTemplate == null || hTemplate.ItemBindingGroup == null) { RestoreValue(itemsControl, ItemsControl.ItemBindingGroupProperty, itemBindingGroup); } } if (hic != null) { if (headerTemplate != null && hic.HeaderTemplate == parentItemsControl.ItemTemplate && hTemplate == null) { RestoreValue(hic, HeaderedItemsControl.HeaderTemplateProperty, headerTemplate); } if (headerTemplateSelector != null && hic.HeaderTemplateSelector == parentItemsControl.ItemTemplateSelector && hTemplate == null) { RestoreValue(hic, HeaderedItemsControl.HeaderTemplateSelectorProperty, headerTemplateSelector); } if (headerStringFormat != null && hic.HeaderStringFormat == parentItemsControl.ItemStringFormat && hTemplate == null) { RestoreValue(hic, HeaderedItemsControl.HeaderStringFormatProperty, headerStringFormat); } } }
private static void RestoreValue(DependencyObject d, DependencyProperty property, ValueAndValueSource v) { Debug.Assert(d != null); Debug.Assert(property != null); Debug.Assert(v != null); if (v.ValueSource == BaseValueSource.Local) { d.SetValue(property, v.Value); } else { d.ClearValue(property); d.CoerceValue(property); } }