The issue could be observed in a scenario with nested RadDock controls. An exception is received when the window state is changed to AutoHide.
Currently tool windows cannot be re-sized proportionally in this scenario.
I've discovered a behavioral issue with the tool-window when one of its containing control's data-binding is updated. I'm designing an application using the MVVM design pattern with a basic View and View-Model. The View is a form that contains a RadDock, ToolWindow containing a Label, and a Button to update the Label's Text; and data-binding setup to the ToolWindow's property "DockState" and a Label's property "Text". The View-Model contains the bound properties "ToolWindow1DockState" and "Label1Text", which implements INotifyPropertyChanged to update the respective controls; and a method used to update Label1's text. After I click "Auto-hide" on ToolWindow1 and click the "Change Text" button, I'm expecting ToolWindow1 to remain in the Auto-hide state. Instead, ToolWindow1 is placed in the Docked state.
In the test scenario the Autohide Windows is hosted in parent RadDock floating windows. The ToolWindow in AutoHide dockstate disposed, after docking the main ToolWindow to tab mode, in a specific scenario.
Description: for example if we have two auto-hidden Tool windows (left and right), first click on the right one but don't pin it, then click on the left one (don't pin it also) and you will notice that for a fraction of time its caption displays the text of the previous window. Then you can click the right window again and you'll see the opposite effect. This tiny fraction of time raises to a significant period of time when tool windows are loaded with multiple controls. AutoHideWindowDisplaying event fires before ActiveWindowChanged event (AutoHideTabStrip.ActiveWindow is the other tool window during AutoHideWindowDisplaying). That is why for a fraction of time (during AutoHideWindowDisplaying event) you can see different caption text. To reproduce: - add RadDock - add two auto-hidden Tool windows (left and right) - first click the right one in order to display the hidden tool window -> for a fraction of time its caption is for the other tool window Workaround: private void radDock1_AutoHideWindowDisplaying(object sender, AutoHideWindowDisplayingEventArgs e) { AutoHideTabStrip autoHide = e.NewWindow.DockTabStrip as AutoHideTabStrip; if (autoHide != null) { autoHide.ActiveWindow.Text = e.DockWindow.Text; } } Another possibility to reduce the flicker is to stop the animations: radDock1.AutoHideAnimation = AutoHideAnimateMode.None;
To reproduce: - add a dock with ToolWindow and DocumentWindow - set the following properties: ToolWindow1.TabStrip.SizeInfo.SizeMode = Telerik.WinControls.UI.Docking.SplitPanelSizeMode.Absolute ToolWindow1.TabStrip.MaximumSize = New Size(94, 400) ToolWindow1.TabStrip.SizeInfo.AbsoluteSize = New Size(94, 400) ToolWindow1.DefaultFloatingSize = New Size(94, 400) - Run the app, change the ToolWindow DockState to floating from context menu in the ToolWindow caption - re-dock the ToolWindow => its sizi is not 94,400 and its SizeMode and AbsoluteSize properties have different values If you perform the same scenario, but make the ToolWindow floating with drag and drop not with the context menu, everything works fine correctly. WORKAROUND: Private Sub RadDock1_DockStateChanging(sender As Object, e As Telerik.WinControls.UI.Docking.DockStateChangingEventArgs) If e.NewWindow Is ToolWindow1 AndAlso e.NewDockState = Telerik.WinControls.UI.Docking.DockState.Docked Then e.NewWindow.TabStrip.SizeInfo.SizeMode = Telerik.WinControls.UI.Docking.SplitPanelSizeMode.Absolute e.NewWindow.TabStrip.MaximumSize = New Size(94, 400) e.NewWindow.TabStrip.SizeInfo.AbsoluteSize = New Size(94, 400) e.NewWindow.DefaultFloatingSize = New Size(94, 400) End If End Sub
Steps to reproduce: - Create a form with RadDock on it - Use the following code in another form: Using frm As New FormWithDock() frm.ShowDialog() End Using - Close the dialog (FormWithDock) -> exception is thrown WORKAROUND - dispose the dock on form closing: Protected Overrides Sub OnClosing(e As System.ComponentModel.CancelEventArgs) RadDock1.Dispose() MyBase.OnClosing(e) End Sub
To reproduce: Follow these steps: 1. Extract the project I have attached and open it in Visual Studio. 2. Run it. 2a. You should note two docked windows on the left (tabbed). 3. Click on the "Open Next Window" button. The first two clicks will simple open the first two docking windows (already open) On the 3rd click another docking window should appear on the right. Click the button a couple more times. You should have 3 docked windows on the right. 4. Now, drag the windows on the left so they are floating and docked together. 5. Click on the Save Layout button at the bottom. 6. Close and rerun the sample. You should note that the floating windows appear at the expected location. Move them off to the side away from their default location (away from the center of the screen) So far so good. 7. Upon reopening the application with toolWindow3, 4 and 5 floating and docked close the floating window. 8. Save the layout. --> This is where the key is... 9. Close and rerun the sample. If you watch quickly you'll see several windows "flicker". They appear and disappear quickly. Now, if you hit the "Open Next Window" button 5x, it will open the first two (already open) and then open the 3rd, 4th and 5th windows. But NOTE - they are NOT docked together. They are also not at the location where you left them (remember you needed to move them to the side)
To reproduce: - Add several tool windows to RadDock. - Make a window floating and then dock it back. - Hide all windows and then save the layout. - Close the application. - Start the application and load the saved layout. - Show all windows again.
To reproduce: radDock1.ElementTree.EnableApplicationThemeName = false; radDock1.ThemeName = "TelerikMetroBlue"; ThemeResolutionService.ApplicationThemeName = "Office2013Light"; Workaround: ThemeResolutionService.ApplyThemeToControlTree(this,"Office2013Light"); radDock1.ThemeName = "TelerikMetroBlue";
To reproduce: - Add a form with two auto-hidden windows - one on the left and one on the right. - Drag one of the windows by just showing it (do not pin it) - The floating window will contain both tool windows, instead of just the dragged one. Workaround: Private Sub RadForm1_Load(sender As Object, e As EventArgs) Handles MyBase.Load RadDock1.DockWindow(ToolWindow2, DockPosition.Right) RadDock1.AutoHideWindows(New DockWindow() {ToolWindow2}, AutoHidePosition.Right) ToolWindow2.Tag = DockPosition.Right RadDock1.AutoHideWindow(ToolWindow1) ToolWindow1.Tag = DockPosition.Left End Sub Private Sub RadDock1_FloatingWindowCreated(sender As Object, e As FloatingWindowEventArgs) Handles RadDock1.FloatingWindowCreated For Each dw As DockWindow In CType(sender, RadDock).DockWindows If dw.Handle <> CType(sender, RadDock).ActiveWindow.Handle Then dw.DockState = dw.PreviousDockState RadDock1.AutoHideWindows(New DockWindow() {dw}, dw.Tag) End If Next End Sub
To reproduce: - Add a panel to a form, dock it to fill the entire space. - Add RadDock to it, set its Dock property to fill. - Add a document window with a grid to it (the grid should fill the entire space). - Start the application and maximize the form. Workaround: - Remove the panel or use RadPanel instead. - Handle the SizeChanged event private void RadForm1_SizeChanged(object sender, EventArgs e) { var window = this.radDock1.ActiveWindow; this.radDock1.ActiveWindow = null; this.radDock1.ActiveWindow = window; }
How to reproduce: 1. Run the attached project 2. Float a tool window 3. Save layout 4. Close the application and start it again 5. Load the saved layout 6. Hide the floating tool window 7. Save layout 8. Close the application and start it again 9. Load layout Notice that the hidden tool window would be floating Workaround: Manually store the hidden tool windows and restore their state after your load the layout: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void radButton1_Click(object sender, EventArgs e) { this.radDock1.SaveToXml(@"..\..\layout.xml"); StringBuilder sb = new StringBuilder(); foreach (DockWindow window in this.radDock1.DockWindows.GetWindows(DockState.Hidden)) { if (window is ToolWindow) { sb.Append(window.Name); sb.Append(";"); } } File.WriteAllText(@"..\..\hidden.txt", sb.ToString()); } private void radButton2_Click(object sender, EventArgs e) { this.radDock1.LoadFromXml(@"..\..\layout.xml"); string[] windows = File.ReadAllText(@"..\..\hidden.txt").Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (var window in windows) { this.radDock1.GetWindow<ToolWindow>(window).Hide(); } } }
How to reproduce: check the attached project and video. Workaround: persist the auto-hidden windows separately public partial class Form1 : Form { public Form1() { InitializeComponent(); this.radDock1.AutoHideWindowDisplaying += RadDock1_AutoHideWindowDisplaying; //Wworkaround this.radDock1.LoadedFromXml += RadDock1_LoadedFromXml; } private void RadDock1_LoadedFromXml(object sender, EventArgs e) { string res = File.ReadAllText(@"..\..\auto-hidden.txt"); foreach (DockWindow window in this.radDock1.GetWindows(typeof(ToolWindow), typeof(HostWindow))) { if (res.IndexOf(window.Name) != -1) { window.DockState = DockState.AutoHide; } } } private void RadDock1_AutoHideWindowDisplaying(object sender, Telerik.WinControls.UI.Docking.AutoHideWindowDisplayingEventArgs e) { } private void button1_Click(object sender, EventArgs e) { StringBuilder sb = new StringBuilder(); foreach (DockWindow window in this.radDock1.GetWindows(typeof(ToolWindow), typeof(HostWindow))) { if (window.DockState == DockState.AutoHide) { sb.AppendLine(window.Name); } } File.WriteAllText(@"..\..\auto-hidden.txt", sb.ToString()); this.radDock1.SaveToXml(@"..\..\layout.xml"); } private void button2_Click(object sender, EventArgs e) { this.radDock1.LoadFromXml(@"..\..\layout.xml"); } }
How to reproduce: try resizing a too window using its splitter Workaround: create a custom RadDock using special layout strategy public class MyRadDock : RadDock { public override string ThemeClassName { get { return typeof(RadDock).FullName; } } protected override SplitContainerLayoutStrategy CreateLayoutStrategy() { MySplitContainerLayoutStrategy strategy = null; if (this.LayoutStrategyType != null) { try { strategy = Activator.CreateInstance(this.LayoutStrategyType) as MySplitContainerLayoutStrategy; } catch { strategy = null; } } if (strategy == null) { strategy = new MySplitContainerLayoutStrategy(); } strategy.RootContainerType = typeof(RadDock); return strategy; } } public class MySplitContainerLayoutStrategy : SplitContainerLayoutStrategy { protected override void Measure() { SplitContainerLayoutInfo layoutInfo = (SplitContainerLayoutInfo)typeof(SplitContainerLayoutStrategy).GetField("layoutInfo", BindingFlags.Instance | BindingFlags.NonPublic). GetValue(this); SplitPanel fillPanel = (SplitPanel)typeof(SplitContainerLayoutInfo).GetField("fillPanel", BindingFlags.Instance | BindingFlags.NonPublic). GetValue(layoutInfo); if (fillPanel == null) { base.Measure(); } this.MeasureWithFillPanel(); typeof(SplitContainerLayoutStrategy).GetMethod("ClampMeasuredLength", BindingFlags.Instance | BindingFlags.NonPublic). Invoke(this, new object[] { }); } private void MeasureWithFillPanel() { FieldInfo layoutInfoFi = typeof(SplitContainerLayoutStrategy).GetField("layoutInfo", BindingFlags.Instance | BindingFlags.NonPublic); SplitContainerLayoutInfo layoutInfo = (SplitContainerLayoutInfo)layoutInfoFi.GetValue(this); int availableLength = (int)typeof(SplitContainerLayoutInfo).GetField("availableLength", BindingFlags.Instance | BindingFlags.NonPublic). GetValue(layoutInfo); int remaining = availableLength; SplitPanel panel; //calculate the desired size of all non-fill panels int desiredNonFillLength = 0; List<SplitPanel> layoutTargets = (List<SplitPanel>)typeof(SplitContainerLayoutInfo).GetField("layoutTargets", BindingFlags.Instance | BindingFlags.NonPublic). GetValue(layoutInfo); SplitPanel fillPanel = (SplitPanel)typeof(SplitContainerLayoutInfo).GetField("fillPanel", BindingFlags.Instance | BindingFlags.NonPublic). GetValue(layoutInfo); int count = layoutTargets.Count; for (int i = 0; i < count; i++) { panel = layoutTargets[i]; if (panel == fillPanel) { continue; } desiredNonFillLength += this.GetLength(panel.SizeInfo.AbsoluteSize); } SplitPanelSizeInfo fillInfo = fillPanel.SizeInfo; int totalSplitterLength = (int)typeof(SplitContainerLayoutInfo).GetField("totalSplitterLength", BindingFlags.Instance | BindingFlags.NonPublic). GetValue(layoutInfo); int layoutableLength = availableLength - totalSplitterLength; int correction = 0; int totalMinLength = (int)typeof(SplitContainerLayoutInfo).GetField("totalMinLength", BindingFlags.Instance | BindingFlags.NonPublic). GetValue(layoutInfo); int desiredFillLength = totalMinLength; if (desiredNonFillLength + desiredFillLength > layoutableLength) { correction = (desiredNonFillLength + desiredFillLength) - layoutableLength; } int remainingCorrection = correction; for (int i = 0; i < layoutTargets.Count; i++) { panel = layoutTargets[i]; if (panel == fillPanel) { continue; } int length = this.GetLength(TelerikDpiHelper.ScaleSize(panel.SizeInfo.AbsoluteSize, new SizeF(1f / panel.SplitPanelElement.DpiScaleFactor.Width, 1f / panel.SplitPanelElement.DpiScaleFactor.Height))); if (remainingCorrection > 0 && panel.SizeInfo.SizeMode != SplitPanelSizeMode.Absolute) { float factor = (float)length / desiredNonFillLength; int panelCorrection = Math.Max(1, (int)(factor * correction)); remainingCorrection -= panelCorrection; length -= panelCorrection; } panel.SizeInfo.MeasuredLength = length; int splitterLength = (int)typeof(SplitContainerLayoutInfo).GetField("splitterLength", BindingFlags.Instance | BindingFlags.NonPublic). GetValue(layoutInfo); remaining -= (panel.SizeInfo.MeasuredLength + splitterLength); } fillPanel.SizeInfo.MeasuredLength = remaining; } }
Workaround: ContextMenuService menuService = this.radDock1.GetService<ContextMenuService>(); menuService.ContextMenuDisplaying += menuService_ContextMenuDisplaying; private void menuService_ContextMenuDisplaying(object sender, ContextMenuDisplayingEventArgs e) { foreach (RadMenuItem listMenuItem in e.MenuItems) { TextPrimitive textPrimitive = listMenuItem.Layout.TextPanel.Children[0] as TextPrimitive; textPrimitive.UseMnemonic = false; } }
To reproduce: - Set the font of the tool window: ((ToolTabStrip)this.toolWindow1.TabStrip).CaptionElement.Font = font1; - Make the tool window floating and then dock it again. - The font is not preserved. Workaround: Set the font in the DockStateChanged event.
The expected behavior should be similar to Visual Studio, once a maximized floating window starts being dragged it should go to a normal state so that the window under it is visible. How to reproduce: just maximize a floating window, then start dragging it from the title bar, the docking guides will appear which do not help much since the window is still maximized. Workaround: handle the Starting event of the DragDropService and change the WindowState of the window public partial class Form1 : Form { public Form1() { InitializeComponent(); DragDropService service = this.radDock1.GetService<DragDropService>(); service.Starting += Service_Starting; } private void Service_Starting(object sender, StateServiceStartingEventArgs e) { FloatingWindow fw = e.Context as FloatingWindow; if (fw != null && fw.WindowState == FormWindowState.Maximized) { fw.WindowState = FormWindowState.Normal; fw.Location = new Point(Cursor.Position.X - fw.Size.Width / 2, Cursor.Position.Y); } } }
Please use attached project and try the following: 1. Run the application and move toolWindow3 from right to the bottom panel. 2. Hide toolWindow3 by 'Toggle' menu item or just close it. 3. Save the layout pressing 'Save' menu item. 4. Close the application and run it again. 5. Restore layout using 'Init' menu item. 6. Press 'Toggle' menu item to show toolWindow3. Workaround: Make the window visible before loading the layout.
To reproduce: please run the attached sample project and follow the steps in the gif file. After some further testing you will notice that the tab items are re-positioned incorrectly when you click a certain tab. It jumps to another location. Workaround: set the MultiLineItemFitMode property to None and specify the DocumentWindow.TabStripItem.Row property in order to arrange the tabs as you wish.