/// <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>
        /// Get the value of SelectedIndex.
        /// </summary>
        /// <param name="item">The model item for a TabControl.</param>
        /// <returns>SelectedIndex of the TabControl.</returns>
        public static int GetDesignTimeSelectedIndex(ModelItem item)
        {
            int selectedIndex = item.GetDesignerProperty(DesignTimeSelectedIndexProperty);

            // check if that tab is really active. If not, then return -1 (none of the tabs are active
            if (item.Content != null &&
                item.Content.Collection.Count > 0 &&
                selectedIndex < item.Content.Collection.Count)
            {
                if (TabItemDesignModeValueProvider.GetDesignTimeIsSelected(item.Content.Collection[selectedIndex]))
                {
                    return(selectedIndex);
                }
            }
            return(-1);
        }
        /// <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>
        /// Determine how the control is parented into the TabItem.
        /// If the control is a TabItem then parent it to the TabControl rather
        /// than the TabItem (think select, copy, paste a TabItem).
        /// If the TabItem has content and the content can accept children
        /// then parent into that and so on.
        /// </summary>
        /// <param name="parent">The parent item.</param>
        /// <param name="childType">The type of child item.</param>
        /// <returns>Redirected parent.</returns>
        public override ModelItem RedirectParent(ModelItem parent, Type childType)
        {
            _canParent = true;

            if (parent == null)
            {
                throw new ArgumentNullException("parent");
            }
            if (childType == null)
            {
                throw new ArgumentNullException("childType");
            }

            // if the tabItem is not activated and/or not within TabControl,
            // redirect to its parent by returning ourselves.
            if (parent.IsItemOfType(MyPlatformTypes.TabItem.TypeId) &&
                parent.Parent != null &&
                (!parent.Parent.IsItemOfType(MyPlatformTypes.TabControl.TypeId) || !TabItemDesignModeValueProvider.GetDesignTimeIsSelected(parent)))
            {
                _canParent = false;
                return(parent);
            }

            // if element being parented is tabItem then add it as sibling of
            // existing tabItems inside TabControl - redirect to parent;
            // else parent this control in TabItem's content, if its Panel.
            if (ModelFactory.ResolveType(parent.Context, MyPlatformTypes.TabItem.TypeId).IsAssignableFrom(childType))
            {
                _canParent = false;
                return(parent);
            }

            if (parent.Content != null && parent.Content.IsSet)
            {
                // if TabItem has a content and if the content is a panel or a contentcontrol,
                // let the content act as the parent.
                ModelItem content = parent.Content.Value;
                if (content != null)
                {
                    ViewItem contentView = content.View;
                    if (content.View != null)
                    {
                        // if the content is not visible but the tabItem is selected,
                        // Update this TabItems Layout.
                        if (!contentView.IsVisible && TabItemDesignModeValueProvider.GetDesignTimeIsSelected(parent))
                        {
                            parent.View.UpdateLayout();
                        }

                        if (contentView.IsVisible &&
                            (content.IsItemOfType(MyPlatformTypes.Panel.TypeId) || content.IsItemOfType(MyPlatformTypes.ContentControl.TypeId)))
                        {
                            return(content);
                        }
                    }
                    else
                    {
                        // TabItem has a content already but the content cannot accept parenting right now
                        // so let tabItem's parent take care of parenting.
                        _canParent = false;
                        return(parent);
                    }
                }
            }

            // TabItem doesnt have any content and now tabItem itself acts as the parent.
            return(base.RedirectParent(parent, childType));
        }
예제 #6
0
        /// <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
            }
        }