I have the class that extends System.Windows.Forms.TabControl
and had implemented drag'n'drop mechanism for its TabPage
s as following:
#region Overriden base methods
protected override void OnDragOver(DragEventArgs e)
{
if (PointedTabPage == null) return;
e.Effect = DragDropEffects.Move;
var dragTab = e.Data.GetData(typeof (ManagedTabPage)) as ManagedTabPage;
if (dragTab == null) return;
int dropIndex = TabPages.IndexOf(PointedTabPage);
int dragIndex = TabPages.IndexOf(dragTab);
if (dragIndex == dropIndex) return;
var modifiedTabPages = new List<ManagedTabPage>(from ManagedTabPage tabPage in TabPages
where TabPages.IndexOf(tabPage) != dragIndex
select TabPages[TabPages.IndexOf(tabPage)] as ManagedTabPage);
modifiedTabPages.Insert(dropIndex, dragTab);
for (byte i = 0; i < TabPages.Count; ++i)
{
var managedTabPage = TabPages[i] as ManagedTabPage;
if (managedTabPage != null && managedTabPage.Uid == modifiedTabPages[i].Uid)
continue;
TabPages[i] = modifiedTabPages[i];
}
SelectedTab = dragTab;
}
protected override void OnMouseDown(MouseEventArgs e)
{
try
{
switch (e.Button)
{
case MouseButtons.Left:
DoDragDrop(PointedTabPage, DragDropEffects.Move);
break;
case MouseButtons.Middle:
CloseTab(PointedTabPage);
break;
}
}
catch (InvalidOperationException)
{
}
finally
{
TabPages.Insert(0, String.Empty);
TabPages.RemoveAt(0);
}
}
#endregion
Nota bene that in the finally
clause of OnMouseDown
method there are 2 lines for workarounding the
problem: for some reason w/o these lines after drag'n'dropping any of TabPage
s alignment of their titles is being wrong:
What should I do to correct this behavior without this smelly workaround? Maybe sending some Windows messages could do the trick? Thanks a lot for any suggestions.
Edit 1. Code of ManagedTabPage
is 100% unimportant (it's just extends TabPage
with some specific properties).
PointedTabPage
is unimportant too, but this is it:
return (from ManagedTabPage tabPage in TabPages
let tabPageIndex = TabPages.IndexOf(tabPage)
where GetTabRect(tabPageIndex).Contains(PointToClient(Cursor.Position))
select TabPages[tabPageIndex]).Single() as ManagedTabPage;
I'm trying to achieve fully-centered alignment of labels. You see, labels on the screenshot didn't centered horizontally?
since you hasn't shared ManagedTabPage
code, i used default TabPage
control
changes are made in method OnDragOver
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace Demo
{
public class MyTabControl : TabControl
{
public MyTabControl()
{
SizeMode = TabSizeMode.Fixed;
ItemSize = new Size(224, 20);
}
#region Overriden base methods
protected override void OnDragOver(DragEventArgs e)
{
if (DesignMode)
return;
if (PointedTabPage == null) return;
e.Effect = DragDropEffects.Move;
var dragTab = e.Data.GetData(typeof(TabPage)) as TabPage;
if (dragTab == null) return;
int dropIndex = TabPages.IndexOf(PointedTabPage);
int dragIndex = TabPages.IndexOf(dragTab);
if (dragIndex == dropIndex) return;
// change position of tab
TabPages.Remove(dragTab);
TabPages.Insert(dropIndex, dragTab);
SelectedTab = dragTab;
base.OnDragOver(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (DesignMode)
return;
switch (e.Button)
{
case MouseButtons.Left:
DoDragDrop(PointedTabPage, DragDropEffects.Move);
break;
case MouseButtons.Middle:
TabPages.Remove(PointedTabPage);
break;
}
}
#endregion
TabPage PointedTabPage
{
get
{
return TabPages.OfType<TabPage>()
.Where((p, tabPageIndex) => GetTabRect(tabPageIndex).Contains(PointToClient(Cursor.Position)))
.FirstOrDefault();
}
}
}
}