TabStrip not always reflecting ActivateWindow() change

3 posts, 1 answers
  1. Michelle
    Michelle avatar
    13 posts
    Member since:
    Nov 2010

    Posted 01 Jan 2013 Link to this post

    Hello,

    I am tasked to replicate the New Tab functionality of Google Chrome. I have attached sample code below that mostly accomplishes this. However there is still one bug that I am unable to fix, and it is related to the RadDock tabstrip not redrawing after ActivateWindow() is called.

    To reproduce this problem, please run the following code. You should see a tab named "New Tab 0" and a mini-tab to its right, which will create additional new tabs if you click on it. Click the mini-tab so you have two named tabs. Then, right-click on the right-most named tab ("New Tab 1", unless you created more) and select "Floating" to pop it out. Here is where the problem happens. We never want the MiniTab to have focus, so the method MiniTabGotFocus() will have been called, which activates the window to its left. However, the tabs are not redrawn to reflect this. BUT, if you click on Form1 parent dialog to give it focus (or close that popped out window), the tabs will immediately redraw correctly. So the window to the left was in fact Activated, but the tabs do not reflect this until Form1 has focus again.

    Does this make sense? I have tried to Invalidate() the TabStrip but that does not force it to redraw. I can only cause it to redraw correctly by clicking on the Form1 parent dialog to give it focus. What I would like help on is how to force the TabStrip to redraw.

    This is using Telerik v2011-8-31.

    Thanks,

    Michelle

    using System;
    using System.Drawing;
    using System.Linq;
    using System.Windows.Forms;
    using Telerik.WinControls.UI.Docking;
     
    namespace WindowsFormsApplication1
    {
        public class Form1 : Form
        {
            #region Windows Form Designer generated code
     
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.IContainer components;
     
            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
     
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                this.chartingDock = new Telerik.WinControls.UI.Docking.RadDock();
                ((System.ComponentModel.ISupportInitialize)(this.chartingDock)).BeginInit();
                this.chartingDock.SuspendLayout();
                this.SuspendLayout();
                //
                // chartingDock
                //
                this.chartingDock.Dock = System.Windows.Forms.DockStyle.Fill;
                this.chartingDock.Location = new System.Drawing.Point(0, 0);
                this.chartingDock.Name = "chartingDock";
                this.chartingDock.Padding = new System.Windows.Forms.Padding(5);
                this.chartingDock.RootElement.MinSize = new System.Drawing.Size(25, 25);
                this.chartingDock.RootElement.Padding = new System.Windows.Forms.Padding(5);
                this.chartingDock.Size = new System.Drawing.Size(573, 397);
                this.chartingDock.SplitterWidth = 4;
                this.chartingDock.TabIndex = 0;
                this.chartingDock.TabStop = false;
                this.chartingDock.Text = "chartingDock";
                //
                // Form1
                //
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(573, 397);
                this.Controls.Add(this.chartingDock);
                this.IsMdiContainer = true;
                this.Name = "Form1";
                this.Text = "Form1";
                ((System.ComponentModel.ISupportInitialize)(this.chartingDock)).EndInit();
                this.chartingDock.ResumeLayout(false);
                this.ResumeLayout(false);
            }
     
            #endregion
     
            private RadDock chartingDock;
     
            public Form1()
            {
                InitializeComponent();
     
                chartingDock.AutoDetectMdiChildren = true;
     
                chartingDock.DockWindowClosed += ChartingDockDockWindowClosed;
                chartingDock.DockWindowClosing += ChartingDockDockWindowClosing;
                chartingDock.TransactionCommitted += ChartingDockTransactionCommitted;
                chartingDock.DockWindowAdded += ChartingDockDockWindowAdded;
                chartingDock.GetDefaultDocumentTabStrip(true).TabStripElement.ItemsChanged += TabStripElement_ItemsChanged;
                 
                EnsureNewChartMiniTabExists();
            }
     
            private int count;
            private void AddTab()
            {
                AddTab("New Tab " + count++);
            }
             
            private void AddTab(string title)
            {
                var f = new ToolWindow
                            {
                                Text = title,
                            };
                if (title == NewChartTabText) f.BackColor = Color.Black;
     
                chartingDock.SetWindowState(f, DockState.TabbedDocument);
            }
             
            private const string NewChartTabText = " ";
            private DockWindow switchTab;
            void ChartingDockDockWindowClosing(object sender, DockWindowCancelEventArgs e)
            {
                var index = Array.IndexOf(chartingDock.DocumentManager.DocumentArray, e.NewWindow);
                switchTab = index == chartingDock.DocumentManager.DocumentArray.Count() - 2 && index > 0
                               ? chartingDock.DocumentManager.DocumentArray[index - 1]
                               : null;
            }
     
            void ChartingDockDockWindowClosed(object sender, DockWindowEventArgs e)
            {
                if (switchTab != null) chartingDock.ActivateWindow(switchTab);
            }
     
            void ChartingDockTransactionCommitted(object sender, RadDockTransactionEventArgs e)
            {
                EnsureNewChartMiniTabExists();
     
                //for when the only chart is double-clicked to pop out, create a new blank chart
                if (chartingDock.DocumentManager.DocumentArray.Where(w => w.Text != NewChartTabText).Count() == 0)
                {
                    AddTab();
                }
     
                //if the committed window was the newcharttab, subscribe to the click event
                var window = e.Transaction.AssociatedWindows.FirstOrDefault();
                if (window != null && window.Text == NewChartTabText)
                {
                    window.TabStripItem.Click -= MiniTabClicked;
                    window.TabStripItem.Click += MiniTabClicked;
                    window.GotFocus += MiniTabGotFocus;
                }
            }
     
            private void EnsureNewChartMiniTabExists()
            {
                if (chartingDock.DocumentManager.DocumentArray.Where(w => w.Text == NewChartTabText).Count() == 0)
                {
                    AddTab(NewChartTabText);
                }
            }
     
            static void ChartingDockDockWindowAdded(object sender, DockWindowEventArgs e)
            {
                var window = e.DockWindow as ToolWindow;
                if (window == null) return;
     
                DockTabStrip strip = e.DockWindow.DockTabStrip;
                if (strip != null)
                {
                    var count = strip.Controls.Count;
                    var index = e.DockWindow.Text == NewChartTabText ? count - 1 : count - 2;
                    if (index < 0) index = 0;
                    strip.Controls.SetChildIndex(e.DockWindow, index);
                }
            }
     
            void TabStripElement_ItemsChanged(object sender, Telerik.WinControls.UI.RadPageViewItemsChangedEventArgs e)
            {
                var window = chartingDock.DocumentManager.DocumentArray.Where(w => w.Text == NewChartTabText).FirstOrDefault() as ToolWindow;
                if (window == null) return;
     
                var tabCount = chartingDock.DocumentManager.DocumentArray.Count();
     
                var index = Array.IndexOf(chartingDock.DocumentManager.DocumentArray, window);
                if (index >= tabCount - 1) return;
                 
                DockTabStrip strip = window.DockTabStrip;
                if (strip == null) return;
                 
                strip.Controls.SetChildIndex(window, tabCount - 1);
            }
             
            private void MiniTabClicked(object sender, EventArgs e)
            {
                AddTab();
            }
             
            private void MiniTabGotFocus(object sender, EventArgs e)
            {
                var tabCount = chartingDock.DocumentManager.DocumentArray.Count();
                if (tabCount < 2) return;
     
                var window = chartingDock.DocumentManager.DocumentArray[tabCount - 2];
                chartingDock.ActivateWindow(window); 
            }
        }
    }
  2. Answer
    Ivan Todorov
    Admin
    Ivan Todorov avatar
    688 posts

    Posted 05 Jan 2013 Link to this post

    Hi Michelle,

    Thank you for contacting us.

    I have investigated your approach but it appears that the issue is much more complex to solve that just forcing a redraw. For some reason, doing the updates the way they are in your implementation puts the tab strip in an invalid internal state. Therefore, I would suggest an alternative approach which uses the NewItem that comes from RadPageView. This approach is much easier to implement and will not cause focus problems and flickering. Please refer to the attached project for additional details.

    I hope this will help you. Feel free to ask if you have any further questions.

    Kind regards,
    Ivan Todorov
    the Telerik team
    Q3'12 SP1 of RadControls for WinForms is out now. See what's new.
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Michelle
    Michelle avatar
    13 posts
    Member since:
    Nov 2010

    Posted 07 Jan 2013 Link to this post

    Thanks very much for the reply and for providing the sample project. I wasn't aware of the NewItem object -- that does indeed greatly simplify what I'm trying to accomplish. I actually prefer the little "+" minitab to the blank minitab.

    Thanks again for the great support!

    Michelle
Back to Top