This is a migrated thread and some comments may be shown as answers.

TabStrip not always reflecting ActivateWindow() change

2 Answers 133 Views
Dock
This is a migrated thread and some comments may be shown as answers.
Michelle
Top achievements
Rank 1
Michelle asked on 02 Jan 2013, 03:49 AM
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 Answers, 1 is accepted

Sort by
0
Accepted
Ivan Todorov
Telerik team
answered on 05 Jan 2013, 08:02 AM
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.
0
Michelle
Top achievements
Rank 1
answered on 07 Jan 2013, 08:28 PM
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
Tags
Dock
Asked by
Michelle
Top achievements
Rank 1
Answers by
Ivan Todorov
Telerik team
Michelle
Top achievements
Rank 1
Share this question
or