/// <summary> /// Capture property changes made by the user and return the design time value. /// </summary> /// <param name="item">The model item for a TabControl.</param> /// <param name="identifier">The property that the user is changing the value of.</param> /// <param name="value">The new value that the user is giving the property.</param> /// <returns>The value to set the property to in the designer.</returns> public override object TranslatePropertyValue(ModelItem item, PropertyIdentifier identifier, object value) { if (identifier == MyPlatformTypes.TabControl.SelectedIndexProperty) { // if SelectedIndex has been modified from XAML/PB, we use that as the value for selectedIndex // otherwise we determine the index of active tabItem and return that as the selected Index // TabControl's DMVP gets called when user changes SelectedIndex from XAML/PB and whenever TabControl gets created/recreated. // TabControl gets recreated when its items collection is updated (adding/removing tabs) // **************Scenario 1:TabItem is added/removed // When a tabItem is added or removed, TabItemAdornerProvider updates the selection for TabItems and we want to retain that selection // This is done by updating DesignTimeSelectedIndex value each time selection for Tabitem is updated and we use this value in TabControls DMVP // *************Scenario 2:User hasa updated SelectedIndex value from XAML/PB // Here we want to use the updated value of SelectedIndex that gets passed into TabControl DMVP // To distinguish between the scenario where Tabcontrol is recreated(Scenario 1) and the case where user has simply updated SelectedIndex property value // we maintain another DesignerProperty called as CurrentSelectedIndexValueProperty, which stores current value of SelectedIndex that has been serialized // We compare CurrentSelectedIndexValueProperty with new value that is passed in to determine whether user has updated SelectedIndex from XAML/PB // If this is the case, we should use updated value of SelectedIndex that user has set and update TabItem selection too if (GetCurrentSelectedIndexPropertyValue(item) != (int)value) { // this is Scenario 2: User has updated SelectedIndex value from XAML/PB SetCurrentSelectedIndexPropertyValue(item, (int)value); if (item.Content.Collection != null && (int)value >= 0 && (int)value < item.Content.Collection.Count) { ModelItem tabItem = item.Content.Collection[(int)value]; TabItemDesignModeValueProvider.SetDesignTimeIsSelected(tabItem, true); return(value); } } // If control flows till here, then its Scenario 1: TabItem is added/removed int selectedIndex = GetDesignTimeSelectedIndex(item); if (selectedIndex != -1) { return(selectedIndex); } else if (item.Properties[identifier].IsSet) { return(value); } else { return(0); } } return(base.TranslatePropertyValue(item, identifier, value)); }
/// <summary> /// When this TabItem is activated set IsSelected to true. /// </summary> /// <param name="item">A ModelItem representing the adorned element.</param> protected override void Activate(ModelItem item) { if (item != null && item.IsItemOfType(MyPlatformTypes.TabItem.TypeId)) { if (Context != null) { Tool tool = Context.Items.GetValue <Tool>(); if (tool == null || tool.FocusedTask == null) { TabItemDesignModeValueProvider.SetDesignTimeIsSelected(item, true); // activate the tab that has been selected item.View.UpdateLayout(); } } } base.Activate(item); }
/// <summary> /// Set the value of SelectedIndex and raise change notification. /// Make the selected TabItem the Active TabItem. /// </summary> /// <param name="item">Model item for the TabControl.</param> /// <param name="value">The SelectedIndex value.</param> public static void SetDesignTimeSelectedIndex(ModelItem item, int value) { item.SetDesignerProperty(DesignTimeSelectedIndexProperty, value); Util.InvalidateProperty(item, MyPlatformTypes.TabControl.SelectedIndexProperty); ModelProperty content = item.Content; ModelItemCollection tabControlChildCollection = null; // activate the corresponding TabItem if (content != null) { tabControlChildCollection = content.Collection; if (tabControlChildCollection != null && value <= tabControlChildCollection.Count) { TabItemDesignModeValueProvider.SetDesignTimeIsSelected(tabControlChildCollection[value], true); } } }
/// <summary> /// Parent the given control into the TabControl. /// </summary> /// <param name="parent">The new parent item for child.</param> /// <param name="child">The child item.</param> public override void Parent(ModelItem parent, ModelItem child) { if (parent == null) { throw new ArgumentNullException("parent"); } if (child == null) { throw new ArgumentNullException("child"); } // Clear existing property values that we don't want to apply to the new container. child.Properties[MyPlatformTypes.FrameworkElement.MarginProperty].ClearValue(); child.Properties[MyPlatformTypes.FrameworkElement.HorizontalAlignmentProperty].ClearValue(); child.Properties[MyPlatformTypes.FrameworkElement.VerticalAlignmentProperty].ClearValue(); bool childIsTabItem = child.IsItemOfType(MyPlatformTypes.TabItem.TypeId); // We always accept parenting in TabControl if there is not active focused Task. // If the control being pasted is not TabItem and TabControl is empty (doesnt have any TabItem(s) in it) // then we inject a TabItem with Grid in TabControl and paste the control under consideration in TabItem. // We inject a TabItem also in cases when active TabItem is not capable of parenting concerned control if (!childIsTabItem) { // Based on evaluation done in RedirectParent(), // if any control other than TabItem is being parented to Control in this Parent() call // then we need to add a new Tabitem with Grid in it try { ModelItem newTabItem = ModelFactory.CreateItem(parent.Context, MyPlatformTypes.TabItem.TypeId, CreateOptions.InitializeDefaults); parent.Content.Collection.Add(newTabItem); // activate the newly added tabItem TabItemDesignModeValueProvider.SetDesignTimeIsSelected(newTabItem, true); int index = parent.Content.Collection.Count - 1; // Find a suitable parent for control to be pasted. // Since we always accept parenting for TabControl when there is no active focused task, // we better make sure this works. AdapterService adapterService = parent.Context.Services.GetService <AdapterService>(); if (adapterService != null) { ModelItem targetParent = FindSuitableParent(adapterService, parent, child.ItemType, index); if (targetParent != null) { ParentAdapter parentAdapter = adapterService.GetAdapter <ParentAdapter>(targetParent.ItemType); parentAdapter.Parent(targetParent, child); } else { Debug.Assert(targetParent != null, "Parenting failed!"); } } } catch (Exception ex) { throw new InvalidOperationException("Parenting Failed", ex.InnerException); } } else { // child being added is a TabItem; child.Properties[MyPlatformTypes.TabItem.IsSelectedProperty].ClearValue(); parent.Content.Collection.Add(child); TabItemDesignModeValueProvider.SetDesignTimeIsSelected(child, true); // Activate the newly added tabItem } }