コード例 #1
0
ファイル: ViewButton.cs プロジェクト: valmac/order-management
        /// <summary>
        /// Called when the parent of the visual MenuItem changes.
        /// </summary>
        /// <param name="oldParent">Old value of the parent of the visual, or null if the visual did not have a parent.</param>
        protected override void OnVisualParentChanged(DependencyObject oldParent)
        {
            // This control will automatically bind to properties on a TreeFrame.  However, the control may be moved from one parent to the next, such as when it
            // moves from the overflow panel back to the main tool bar.  To handle the fact that the visual tree can change, this method is need to disconnect
            // the control when it is in limbo and reconnect it when it's found a new home.
            ExplorerFrame explorerFrame = VisualTreeExtensions.FindAncestor <ExplorerFrame>(this);

            if (explorerFrame == null)
            {
                // Disconnect the bindings to the ancestor TreeFrame when the control is floating without a TreeFrame ancestor.
                BindingOperations.ClearBinding(this, ViewButton.ViewValueProperty);
                BindingOperations.ClearBinding(this, ViewButton.ViewModeProperty);
            }
            else
            {
                // This will automatically connect the Value property to the ancestor TreeView when it's found a new home.
                Binding viewValueBinding = new Binding();
                viewValueBinding.Path   = new PropertyPath("ViewValue");
                viewValueBinding.Source = explorerFrame;
                viewValueBinding.Mode   = BindingMode.TwoWay;
                BindingOperations.SetBinding(this, ViewButton.ViewValueProperty, viewValueBinding);
            }

            // Allow the base class to handle the rest of the event.
            base.OnVisualParentChanged(oldParent);
        }
コード例 #2
0
        /// <summary>
        /// Invoked when an unhandled Mouse.MouseMove attached event reaches an element in its route that is derived from this class.
        /// </summary>
        /// <param name="e">The MouseEventArgs that contains the event data.</param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            // Validate the parameters.
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }

            // This will highlight (and bring comletely into view) the element underneath the mouse.  There is a verion of this in the WPF ComboBox that waits for a
            // MouseEnter event from the element and then tries to figure out if mouse movement caused the event.  This is cumbersome because a MouseEnter event can
            // be caused by the mouse being moved over the element, or the element being scrolled underneath the mouse.  An element being scrolled underneath a
            // mouse that hasn't moved can cause a false highlighting of the element, so a whole 'nuther set of logic was required to see if the mouse had actually
            // moved. Since this event assumes that the mouse has moved, it is simpler just to find out what element is under the mouse and change the highlight if
            // it wasn't the last thing highlighted.
            DependencyObject dependencyObject = this.InputHitTest(e.GetPosition(this)) as DependencyObject;
            HighlightElement highlightElement = VisualTreeExtensions.FindAncestor <HighlightElement>(dependencyObject);

            if (highlightElement != this.HighlightedElement)
            {
                highlightElement.BringIntoView();
                this.HighlightedElement = highlightElement;
            }

            // Because an intermediate class in the inheritance might implement this method, we recommend that you call the base implementation in your
            // implementation.
            base.OnMouseMove(e);
        }
コード例 #3
0
        /// <summary>
        /// Occurs when the element is laid out, rendered, and ready for interaction.
        /// </summary>
        /// <param name="sender">The object where the event handler is attached.</param>
        /// <param name="e">The event data.</param>
        void OnLoaded(Object sender, RoutedEventArgs e)
        {
            // The GadgetBar is actually not part of the ExplorerPage even though its resources are declared here.  When the ExplorerPage is hooked into the
            // ExplorerFrame, the frame gets a message asking it to use the GadgetBar (which is really just an ObservableCollection of Gadgets) as the ItemsSource
            // in the ExplorerBar control on the frame.  So The GadgetBar property in this control is really just a collection that is used by the main frame window
            // of the application.  As such, it has no way of routing commands back to the ExplorerPage where the Gadget was declared.  If we left the CommandTarget
            // alone, the Command Routing would attempt to find the element with the focus, but that is too random for most high level, application-type commands.
            // This will direct every Gadget with a command, that has a corresponding CommandBinding, to target this page when the command is invoked.
            foreach (Gadget gadget in this.GadgetBar)
            {
                foreach (CommandBinding commandBinding in this.CommandBindings)
                {
                    if (gadget.Command == commandBinding.Command && gadget.CommandTarget == null)
                    {
                        gadget.CommandTarget = this;
                    }
                }
            }

            // The data context for the page is the item selected in the frame.
            ExplorerFrame explorerFrame = VisualTreeExtensions.FindAncestor <ExplorerFrame>(this);

            if (explorerFrame != null)
            {
                this.DataContext = explorerFrame.SelectedItem;
            }

            // This will send a message up to the frame that there is a new set of gadgets available.  The frame will use this instance's collection directly so
            // that changing the local collection here will change the way the gadgets are displayed in the frame's toolbar.
            if (this.GadgetBar.Count != 0)
            {
                this.RaiseEvent(new ItemsSourceEventArgs(ExplorerFrame.GadgetBarChangedEvent, this.GadgetBar));
            }
        }
コード例 #4
0
        /// <summary>
        /// Occurs when the element is laid out, rendered, and ready for interaction.
        /// </summary>
        /// <param name="sender">The object where the event handler is attached.</param>
        /// <param name="routedEventArgs">The event data.</param>
        void OnLoaded(Object sender, RoutedEventArgs routedEventArgs)
        {
            // This object will automatically bind itself to a parent TreeFrame when one is available.
            ExplorerFrame explorerFrame = VisualTreeExtensions.FindAncestor <ExplorerFrame>(this);

            if (explorerFrame != null)
            {
                // The children of a Frame do not automatically inherit the data context of the parent window.  This is likely due to the fact that pages are not
                // naturally kept alive when the navigation moves away.  So any data binding operation must be established or re-established when the page is
                // loaded and must be cleared when the page is unloaded.  This will bind this page to the context of the parent frame (for now).
                Binding dataContextBinding = new Binding();
                dataContextBinding.Path   = new PropertyPath("DataContext");
                dataContextBinding.Source = explorerFrame;
                dataContextBinding.Mode   = BindingMode.OneWay;
                BindingOperations.SetBinding(this, ViewPage.DataContextProperty, dataContextBinding);

                // The Source property binding allows a change to the property to propogate up to the container.
                Binding sourceBinding = new Binding();
                sourceBinding.Path   = new PropertyPath("Source");
                sourceBinding.Source = explorerFrame;
                sourceBinding.Mode   = BindingMode.TwoWay;
                BindingOperations.SetBinding(this, ViewPage.SourceProperty, sourceBinding);

                // This value indicates what kind of view is used to display the items.
                Binding viewValueBinding = new Binding();
                viewValueBinding.Path   = new PropertyPath("ViewValue");
                viewValueBinding.Source = explorerFrame;
                viewValueBinding.Mode   = BindingMode.TwoWay;
                BindingOperations.SetBinding(this, ViewPage.ViewValueProperty, viewValueBinding);
            }
        }
コード例 #5
0
        /// <summary>
        /// Presents the user with a dialog box for managing the columns.
        /// </summary>
        /// <param name="sender">The object that originated the event.</param>
        /// <param name="e">The event data.</param>
        void OnMore(Object sender, ExecutedRoutedEventArgs e)
        {
            // This will extract the context menu that generated this event from the generic arguments.
            ContextMenu contextMenu = sender as ContextMenu;

            // From the context menu, we need the target that orignated the event and from that we can finally get the column set on which we want to operate.
            ColumnViewColumnHeader columnViewColumnHeader = contextMenu.PlacementTarget as ColumnViewColumnHeader;
            ListView   listView   = VisualTreeExtensions.FindAncestor <ListView>(columnViewColumnHeader);
            ColumnView columnView = listView.View as ColumnView;

            // This dialog box is used to add, remove, move or resize the columns in the view.  It can't operate directly on the set of columns because those are
            // linked dynamically to the view, so we'll create a shallow clone of the values.
            ColumnViewChooseDetail columnViewChooseDetail = new ColumnViewChooseDetail();

            foreach (ColumnViewColumn columnViewColumn in columnView.Columns)
            {
                columnViewChooseDetail.ListBox.Items.Add(new ColumnDescription(columnViewColumn));
            }

            // Present the user with the chance to manage the columns.  If the OK key is hit then copy the values out of the shallow copy and into the live column
            // set where they'll update the view.
            if (columnViewChooseDetail.ShowDialog() == true)
            {
                foreach (ColumnDescription columnDescription in columnViewChooseDetail.ListBox.Items)
                {
                    ColumnViewColumn columnViewColumn = columnDescription.Column;
                    columnViewColumn.IsVisible = columnDescription.IsVisible;
                    columnViewColumn.Width     = columnDescription.Width;
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Invoked when the parent of this element in the visual tree is changed. Overrides OnVisualParentChanged.
        /// </summary>
        /// <param name="oldParent">The old parent element. May be null to indicate that the element did not have a visual parent previously.</param>
        protected override void OnVisualParentChanged(DependencyObject oldParent)
        {
            // This is a 'self-binding' control.  When the parent changes, clear the relationship to the old parent.
            if (BindingOperations.IsDataBound(this.viewSlider, ViewSlider.ValueProperty))
            {
                BindingOperations.ClearBinding(this.viewSlider, ViewSlider.ValueProperty);
            }

            // When the button on the ViewButton control is used to select a different mode, the slider needs to reflect that mode and vica-versa.  This will walk
            // up the visual tree until the owner of this drop down window is found and attach itself to the property that controls the display mode and the
            // scaling.  Alternatively, when the slider is moved, the value of the display mode and scale will change with the value of the slider.
            Binding valueBinding = new Binding();

            valueBinding.Path   = new PropertyPath("ViewValue");
            valueBinding.Source = VisualTreeExtensions.FindAncestor <ViewButton>(this);
            valueBinding.Mode   = BindingMode.TwoWay;
            BindingOperations.SetBinding(this.viewSlider, ViewSlider.ValueProperty, valueBinding);

            // There is significant processing in the base class for this method.  Removing this call will have adverse side effects.
            base.OnVisualParentChanged(oldParent);
        }
コード例 #7
0
        /// <summary>
        /// Occurs when a particular instance of a context menu opens.
        /// </summary>
        /// <param name="sender">The object where the event handler is attached.</param>
        /// <param name="e">The event data.</param>
        void OnOpened(Object sender, RoutedEventArgs e)
        {
            // Extract the context menu from the generic event arguments.
            ContextMenu contextMenu = sender as ContextMenu;

            // We're going to clean out the context menu and re-evaluate the contents based on the context where the menu was opened.
            contextMenu.Items.Clear();

            // This is the header that opened the context menu.  From it, we need the ListView that hosts the ColumnView (that contains all the columns that we're
            // trying to manage with this context menu).
            ColumnViewColumnHeader columnViewColumnHeader = contextMenu.PlacementTarget as ColumnViewColumnHeader;
            ListView   listView   = VisualTreeExtensions.FindAncestor <ListView>(columnViewColumnHeader);
            ColumnView columnView = listView.View as ColumnView;

            // The task now is to fill in the menu items.  We don't allow the user to resize a padding column, but will allow them to resize all the columns.
            if (columnViewColumnHeader.Role != ColumnViewColumnHeaderRole.Padding)
            {
                this.Items.Add(new MenuItem()
                {
                    Command = Commands.FitColumn, CommandTarget = columnViewColumnHeader, Header = "Size Column to Fit"
                });
            }
            this.Items.Add(new MenuItem()
            {
                Command = Commands.FitAllColumns, CommandTarget = listView, Header = "Size All Columns to Fit"
            });
            this.Items.Add(new Separator());

            // This will order the fixed menu items by their ordinal.  An 'ordinal' is a numeric value that the designer can assign to the fixed menu items to
            // determine the order (or even if they'll appear) as a fixed menu item (that is, a quick way to add or remove a column, as opposed to selecting the
            // 'More...' button and using the list box to select an column).
            SortedList <Int32, ColumnViewColumn> commonColumns = new SortedList <Int32, ColumnViewColumn>();

            foreach (ColumnViewColumn columnViewColumn in columnView.Columns)
            {
                if (columnViewColumn.Ordinal.HasValue && !commonColumns.ContainsKey(columnViewColumn.Ordinal.Value))
                {
                    commonColumns.Add(columnViewColumn.Ordinal.Value, columnViewColumn);
                }
            }

            // This will create a dedicated menu item for each of the columns that has been assigned an 'ordinal'.  This allows the user to quickly add or remove
            // frequently used columns.  Note that we attempt to format the column headers the way they would appear in the actual column header.
            foreach (KeyValuePair <Int32, ColumnViewColumn> keyValuePair in commonColumns)
            {
                ColumnViewColumn columnViewColumn = keyValuePair.Value;
                MenuItem         menuItem         = new MenuItem();
                Binding          isVisibleBinding = new Binding()
                {
                    Path = new PropertyPath(ColumnViewColumn.IsVisibleProperty)
                };
                isVisibleBinding.Source = columnViewColumn;
                BindingOperations.SetBinding(menuItem, MenuItem.IsCheckedProperty, isVisibleBinding);
                menuItem.Header      = columnViewColumn.Description;
                menuItem.IsCheckable = true;
                this.Items.Add(menuItem);
            }

            // Place a separator in the context menu if there is a section above it with dedicated menu items for the column visibility settings.
            if (commonColumns.Count != 0)
            {
                this.Items.Add(new Separator());
            }

            // Finally, a general purpose dialog box for managing the column set.
            this.Items.Add(new MenuItem()
            {
                Command = Commands.More, Header = "More..."
            });
        }
コード例 #8
0
        /// <summary>
        /// Measures the child elements of a Teraque.BreadcrumbPanel prior to arranging them during the ArrangeOverride pass.
        /// </summary>
        /// <param name="availableSize">A maximum Size to not exceed.</param>
        /// <returns>A Size that represents the element size you want.</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            // This panel can provide no useful measurement or layout if it isn't an items host.
            if (!this.IsItemsHost)
            {
                return(availableSize);
            }

            // This is the collection that is associated with the user interface in this panel.  Items that can fit in the panel or have been explicitly set to be
            // visible will be added to this collection.
            this.UIElementCollection.Clear();

            // This is the only place where the decision about what items actually appear in the panel is made.  An event associated with this control is invoked
            // when visible items are added or removed.  Since the GadgetBar will go through several passes of adding and removing items before it determines what
            // fits and what doesn't, a simple ObservableList-type trigger wouldn't work because there'd be too many false signals.  To provide the required
            // functionality, a copy of the list is made here before the measurement and will be used later to determine if the final set of items has changed.
            List <Object> originalList = new List <Object>();

            foreach (Object item in this.GadgetBar.PanelItems)
            {
                originalList.Add(item);
            }

            // This observable list maintains the logical relationship with the parent menu.  When items are added to or removed from this list a trigger in the
            // GadgetBar will add them to or remove them from the logical children of that control.
            this.GadgetBar.PanelItems.Clear();

            // This observable list maintains the logical relationship with the overflow menu.  These relationships must be managed manually.  When an item is added
            // to the overflow panel it must be removed from the main panel.  It must also be added at the exact same time or orphaned MenuItems will generate
            // messages about data binding failures.
            this.GadgetBar.OverflowItems.Clear();

            // After each pass through the measuring the child controls the logical items will be shifted around.  Some of them will be moved to the overflow panel
            // and some will remain in the main panel.  This confuses the items container generator when it comes time to creating the containers.  The original
            // logical relationship of the items is restored here in order to set things right for the ItemsContainerGenerator.
            ItemsControl itemsControl = this.GadgetBar as ItemsControl;

            foreach (Object item in itemsControl.Items)
            {
                this.GadgetBar.PanelItems.Add(item);
            }

            // The main panel must make a proper measurement of all the child controls to determine if there's enough space.  If there isn't, then the items are
            // moved out of the main panel and into an overflow panel in a very well prescribed order.  The trouble with this is that items don't move out of their
            // containers very well.  They seem to be broken when another items container tries to use the same item.  In this case, the items container for the
            // items in the main panel are broken when the overflow panel creates menu item containers for them.  There seems to be no mechanism to repair a broken
            // container so they are regenerated here.  Also, recycling doesn't appear to work.  Once a container is broken, apparently it must be discarded so each
            // time through the measure override a new set of containers is generated.
            IItemContainerGenerator iItemContainerGenerator = this.ItemContainerGenerator as ItemContainerGenerator;

            iItemContainerGenerator.RemoveAll();

            // The order of the items as they come out of the generator is used to determine their order in the overflow panel.  This table is used to determine the
            // relative order of items as they are moved to the overflow panel.
            Dictionary <Object, Int32> itemTable = new Dictionary <object, int>();

            // When items are moved out of the main panel and into the overflow panel they keep the same relative order.  The algorithm to do this is a bit tricky
            // as the items are moved in several passes.  The first pass takes the items that are marked to always appear in the overflow panel.  The next pass
            // takes the items from the visible panel that are marked to be moved as needed.
            Int32 itemIndex     = 0;
            Int32 overflowIndex = 0;
            Int32 panelIndex    = 0;

            // This variable will capture the overflow menu item, if it exists as part of the members of the panel.  The overflow menu item has special properties
            // in that an item that doesn't fit into the panel will be made children of this item.
            OverflowItem overflowItem = null;

            GadgetBar gadgetBar = VisualTreeExtensions.FindAncestor <GadgetBar>(this) as GadgetBar;

            System.ComponentModel.ICollectionView iCollectionView = System.Windows.Data.CollectionViewSource.GetDefaultView(gadgetBar.ItemsSource);
            iCollectionView.Refresh();

            // This will generate a collection of containers from the items hosted by the parent.  Note that these items are not associated with a user interface
            // yet.  This collection will be split into items that appear on the panel and those available through the overflow control.  The containers must be
            // created each time through the measure override because broken containers can't be repaired or recycled.  When another container has usurped the
            // contained item, the original container is broken.  This happens when an item is moved from the main panel to the overflow panel.
            using (iItemContainerGenerator.StartAt(new GeneratorPosition(-1, 0), GeneratorDirection.Forward))
            {
                // This will generate a new container for each item and determin whether it belongs in the main panel or the overflow panel.
                UIElement uiElement;
                while ((uiElement = iItemContainerGenerator.GenerateNext() as UIElement) != null)
                {
                    // This allows the host to make modifications to the container before it is displayed.  For example, a GadgetBar would assign a style to the item
                    // container based on the item type.
                    iItemContainerGenerator.PrepareItemContainer(uiElement);

                    // Overflow menu items have special meaning for the panel.  Any item that doesn't fit into the panel will be added to this item.
                    OverflowItem generatedOverflowItem = uiElement as OverflowItem;
                    if (generatedOverflowItem != null)
                    {
                        overflowItem = generatedOverflowItem;
                        continue;
                    }

                    // This constructs a mapping of the item to its ordinal and is used to determine the relative order of the overflow items as they are added to
                    // the overflow panel in multiple passes.
                    Object item = this.ItemContainerGenerator.ItemFromContainer(uiElement);
                    itemTable.Add(item, itemIndex++);

                    // The OverflowMode attached property can be use to force an item into the overflow panel.
                    switch (GadgetBar.GetOverflowMode(uiElement))
                    {
                    case OverflowMode.Always:

                        // These items always appear in the overflow panel in the order they were added to the Items property of the GadgetBar.
                        this.GadgetBar.PanelItems.Remove(item);

                        // Conversely the item removed from the main panel is moved into the overflow panel.  The same item can not be the logical child of two
                        // windows at the same time.  The observable lists will take care of removing the child from one parent and giving it to the other.
                        this.GadgetBar.OverflowItems.Insert(overflowIndex, uiElement);
                        overflowIndex++;

                        // Remove the generated item if it has no place in the main panel.
                        Int32             containerIndex    = this.ItemContainerGenerator.IndexFromContainer(uiElement);
                        GeneratorPosition generatorPosition = iItemContainerGenerator.GeneratorPositionFromIndex(containerIndex);
                        iItemContainerGenerator.Remove(generatorPosition, 1);

                        break;

                    default:

                        // These items include the ones that will move to the overflow panel if needed and the ones that never move.  Note that the collection of
                        // containers is not the same as the collection of items. The collection of items is a logical organization whereas the collection of
                        // containers is visual.  This pass is organizing the visual elements. Also note that the overflow button is always part of the
                        // BreadcrumbBar and always appears as the first item.
                        this.UIElementCollection.Insert(panelIndex, uiElement);
                        panelIndex++;

                        break;
                    }
                }
            }

            // This will insert the overflow item when it has child items that can be displayed.  The overflow item always appears at the left edge of the
            // BreadcrumbBar when it's visible.  In the case where there is only one element at the root of the directory, the overflow item is hidden because
            // there is nothing to navigate to in this situation.
            if (overflowItem.Items.Count != 0)
            {
                this.UIElementCollection.Insert(0, overflowItem);
            }

            // This keeps track of how much space in the panel is occupied by the items as they are laid out.
            Size allocatedSize = new Size();

            // This constraint is used to allow the controls to measure themselves out in the direction in which the panel is oriented.  That is, if it has a
            // horizontal orientation then an infinite amount of space is given during the measurement process in this direction.  It allows the controls the
            // calculate their theoretical size.  If the item doesn't fit, it will be removed from the panel and its desired size will be recalculated inside the
            // overflow panel.  If it does fit, then the desired size is the actual size it is given in the panel.
            Size infiniteSize = new Size(Double.PositiveInfinity, availableSize.Height);

            // This pass will measure everything that wants to appear in this panel.  An infinite amount of room is given in the direction in which this panel is
            // oriented so the measurement operation won't be constrained.  Another pass will actually determine if the items fit or not.
            foreach (UIElement uiElement in this.UIElementCollection)
            {
                uiElement.Measure(infiniteSize);
                allocatedSize = new Size(allocatedSize.Width + uiElement.DesiredSize.Width, Math.Max(allocatedSize.Height, uiElement.DesiredSize.Height));
            }

            // This will attempt to make sure that everything can fit into the alloted space.  If there isn't enough room and individual items are willing to be
            // placed into the overflow panel, then they are removed from this panel.  This concept is very important because moving logical children from one
            // container to another breaks the container and it can't be repaired.  That is why the items must be regenerated each time the panel is measured.  The
            // items are moved in two passes: the items on the near side of the panel are removed before the items on the far side.
            Double availableLength = availableSize.Width;
            Double allocatedLength = allocatedSize.Width;

            if (allocatedLength > availableLength)
            {
                // The calculation of what items can appear in the overflow panel is accomplished in two passes.  The first pass will look at the near-aligned items
                // and move them into the overflow panel starting from the farthest item to the item to the nearest until the items fit in the available space.
                Int32 index = 0;
                while (allocatedLength > availableLength && index >= 0 && index < this.UIElementCollection.Count)
                {
                    // This element will be examined to see if it can be removed from the panel when there are too many elements to fit.
                    UIElement uiElement = this.UIElementCollection[index];

                    // The overflow item is never considered for removal from the main panel.
                    if (uiElement is OverflowItem)
                    {
                        index++;
                        continue;
                    }

                    // This will move the next element in the panel into the overflow panel as needed.  Note that the overflow button is never moved into the
                    // overflow panel.
                    if (GadgetBar.GetOverflowMode(uiElement) == OverflowMode.AsNeeded)
                    {
                        // This element will no longer appear on the main panel.  This will remove both the visual and the logical relationship.  If the logical
                        // relationship isn't broken then this item can't be added to the overflow panel as an item can have only one logical parent at a time.  If
                        // the proper logical relation isn't made then the containers and the contents won't pick up the proper styles.  This is particularly
                        // important for menu items as top level items behave differently than sub-menu items.
                        this.UIElementCollection.Remove(uiElement);
                        Object item = this.ItemContainerGenerator.ItemFromContainer(uiElement);
                        this.GadgetBar.PanelItems.Remove(item);

                        // This will provide the housekeeping with the ItemsContainerGenerator by removing containers that aren't needed for this panel.
                        Int32             containerIndex    = this.ItemContainerGenerator.IndexFromContainer(uiElement);
                        GeneratorPosition generatorPosition = iItemContainerGenerator.GeneratorPositionFromIndex(containerIndex);
                        iItemContainerGenerator.Remove(generatorPosition, 1);

                        // Insert the item into the overflow panel in the same order in which it appears in the panel.
                        this.GadgetBar.OverflowItems.Insert(0, item);

                        // These act as cursors when ordering the items in the overflow panel.
                        overflowIndex++;
                        panelIndex--;

                        // Adjust the available space by the size of the item that was just removed to the overflow panel.
                        allocatedLength -= uiElement.DesiredSize.Width;
                    }
                    else
                    {
                        // Consider the next container in the panel.
                        index++;
                    }
                }
            }

            // This will advise any listeners that the items in the panel have changed.  Since panels are not part of a standard template, this information is
            // normally inaccessible to a parent class except as events bubbled up through the visual tree hierarchy.
            Boolean isEqual = this.GadgetBar.PanelItems.Count == originalList.Count;

            for (Int32 index = 0; isEqual && index < this.GadgetBar.PanelItems.Count; index++)
            {
                isEqual = Object.Equals(this.GadgetBar.PanelItems[index], originalList[index]);
            }
            if (!isEqual)
            {
                this.RaiseEvent(new RoutedEventArgs(GadgetPanel.ItemsChangedEvent, this));
            }

            // This is how much room is needed for the panel.  Note that the maximum height (or width) of the tool panel is determined by all the items whether they
            // appear in the tool panel or the overflow panel.  This one-size-fits-all approach keeps the panel from jumping around as items are added from or
            // removed to the overflow panel.
            return(new Size(allocatedLength, allocatedSize.Height));
        }