I cannot seem to find any code examples of how to create a floating LayoutPanel from code other than one that referred to the ExtraBars namespace that doesn't seem to work with the DXDocking product. I need to create a floating panel whose content is derived from a bound custom object using a DataTemplate. Your help will be greatly appreciated.
Tom
Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.
Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.
Hi Tom,
To create a floating panel from code, you need to create a FloatGroup for this panel (or add the panel to an existing one). FloatGroup provides properties to a control where a panel should reside - FloatPosition and FloatSize. Here is the code snippet illustrating how to create a new floating layout panel:
LayoutPanel layoutPanel = new LayoutPanel() { Caption = "Floating panel" }; FloatGroup floatGroup = new FloatGroup() { FloatSize = new Size(200, 400), FloatLocation = new Point(-60, -60) }; floatGroup.Items.Add(layoutPanel); dockLayoutManager1.FloatGroups.Add(floatGroup);
Does this solution meet your requirements?
Thanks,
Ted
Ted,
Thank you. That does seem to work. I am sorry if my next questions sound lame, but you can save me much time with an answer that works.
First, I have a DataTemplate:
<DataTemplate x:Key="SensorStatusDataTemplate">
<StackPanel Orientation="Vertical">
<!-- Heading -->
<TextBlock FontSize="20" FontWeight="Bold" Margin="0,0,5,0" HorizontalAlignment="Center"
Text="{Binding Path=UnitID}" />
<!-- Content -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" FontStyle="Italic" Text="Device Type:" />
<TextBlock Grid.Column="1" Grid.Row="0" Margin="2,0,0,0" Text="{Binding Path=DeviceType}" />
<TextBlock Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right" FontStyle="Italic" Text="Current Status:" />
<TextBlock Grid.Column="1" Grid.Row="1" Margin="2,0,0,0" Text="{Binding Path=StatusDescription}" />
<TextBlock Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" FontStyle="Italic" Text="Last Update At:" />
<TextBlock Grid.Column="1" Grid.Row="2" Margin="2,0,0,0" Text="{Binding Path=LastUpdateAt}" />
<TextBlock Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" FontStyle="Italic" Text="Is Faulted:" />
<TextBlock Grid.Column="1" Grid.Row="2" Margin="2,0,0,0" Text="{Binding Path=IsFaulted}" />
<TextBlock Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" FontStyle="Italic" Text="Is Jammed:" />
<TextBlock Grid.Column="1" Grid.Row="2" Margin="2,0,0,0" Text="{Binding Path=IsJam}" />
<TextBlock Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" FontStyle="Italic" Text="Is Off:" />
<TextBlock Grid.Column="1" Grid.Row="2" Margin="2,0,0,0" Text="{Binding Path=IsOff}" />
<TextBlock Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" FontStyle="Italic" Text="Is On:" />
<TextBlock Grid.Column="1" Grid.Row="2" Margin="2,0,0,0" Text="{Binding Path=IsOn}" />
</Grid>
</StackPanel>
</DataTemplate>
that represents the layout of the information to be displayed for this floating panel. How would you suggest that I get my snazzy new floating panel to contain these elements and to what would I bind the custom object that contains the data values in order to populate the template?
Second, my application will, potentially, instantiate an unlimited number of these floating panels, each for a separate device whose status is to be displayed. Should they all be added to the same FloatGroup (to get the same size and position values)? If so, how do I acquire a reference to the dynamically created FloatGroup? Or how do I create a non-visible FloatGroup in XAML to which all these dynamically-created panels can be added?
Thanks in advance for your help!
Regards,
Tom
Hi Tom,
I have created a sample project that illustrates how to use ContentTemplate for a layout panel. You will find it in the attachment.
As for the groups, whether you need to create new groups or use existing ones depends on the layout you wish to build, . When you place each layout panel to a separate floating group, you get an independent window for each panel. When you place a panel to the existing group, panels within this group will be docked in some way. Still, a user will be able to undock and split those panels.
Thanks,
Ted
Ted,
You have given me precisely the information I needed to speed my solution! Once again, you guys have come through in an outstanding manner!
Thank you for your help!
Regards,
Tom
Sorry, I guess I spoke too soon!
I have now created a FloatGroup via XAML:
<dxdo:DockLayoutManager.FloatGroups>
<dxdo:FloatGroup x:Name="DeviceStatusDetailsFloatGroup" Visibility="Hidden" FloatSize="260, 400" FloatLocation="40, 40"/>
</dxdo:DockLayoutManager.FloatGroups>
and add to it a new floating panel in code:
LayoutPanel lp = new LayoutPanel();
lp.Caption = shape.UnitID;
lp.ContentTemplate = (DataTemplate)FindResource("SensorStatusDataTemplate");
DeviceStatusEntry dse = null;
if (statusValues.TryGetValue(shape.UnitID, out dse))
{
lp.Content = dse.StatusValue;
dockLayoutManager.DockController.Float(lp);
}
FloatGroup fg = DeviceStatusDetailsFloatGroup as FloatGroup;
if (fg != null)
{
fg.Items.Add(lp);
fg.Visibility = System.Windows.Visibility.Visible;
}
Unless I play the game with the FloatGroup's visibility, it appears and is annoyingly visible but empty. All is well, however -- until I close or dock the last LayoutPanel contained in the FloatGroup, that is. Although the FloatGroup is no longer visible, it still exists; however, adding a new LayoutPanel to it does not yield a visible FloatGroup/panel! What must I do to make them visible again?
Thanks again,
Tom
Hi Tom,
I'm afraid I don't quite understand all the steps you're performing in this code. Are you making a panel float and then adding this already floating panel to another floating group? Would you please send me a sample project with this code, so that I can examine it on my side and see how it operates.
Thanks,
Ted
Ted,
I apologize for my lack of clarity. I have attached a sample project that manifests the behavior: right-click within either TabbedGroup panel and a context menu will appear; click the single MenuItem and a new floating panel will appear; close/remove it (click the "x"); right-click within the TabbedGroup panel again; click the context menu MenuItem again; nothing appears (you will find, however, that the FloatGroup still exists).
Let me explain what I am trying to accomplish and, perhaps, you can determine if creating a floating panel is even the appropriate approach to take.
My application displays the layout of a large conveyor system. The conveyor is depicted by many custom UIElements arranged on several Canvases, each residing on a LayoutPanel that is a member of a TabbedGroup. The custom UIElements change appearance to reflect the status of the conveyor section that they represent. I want to provide my users, in response to a right-click on any custom UIElement, a panel containing the details of the corresponding conveyor section's status. I expect the user will want, once this "status details" panel is displayed, to either dismiss (close/remove) it or leave it visible somewhere. I think (I won't know until I experiment and see how it looks/feels) that it may make sense to dock a "status details" panel to one side of the layout panel containing the right-clicked UIElement. I can certainly live with a "status details" panel being docked (rather than floating) when it is first created as long as it is fully visible immediately after being created.
So, two questions at this point:
1) Is adding my "status details" panel to a FloatGroup the "right" way to approach this?
2) Why, after the last panel is removed from the FloatGroup is the FloatGroup no longer visible and what do I need to do to make it visible again?
Thanks in advance!
Regards,
Tom
Hi Tom,
Thank you for the sample project. This issue occurs because once all children of a group are closed, this group is removed from the corresponding collection of the DockLayoutManager component. I have added the code that returns the group back to the FloatingGroups collection and now everything operates as expected. Attached is the modified sample project.
Thanks,
Ted
Ted,
Once again, thank you for providing me with the answer to what must seem a dumb question. Your enhancement to my test project works beautifully. May I bother you with one more question, not necessarily related to the Subject as stated above? I notice that when I dock one of my newly-created "status details" panels, its width is initially set to half that of the panel to which it is docked. Surely there must be a way of establishing the initial size that a panel takes when it is docked, right? I have looked without success in the places I expected to find it. Can you tell me how I can control this?
Regards,
Tom
Hi Tom,
You can use the ItemWidth property to specify the width of a panel. I have attached a small sample project to illustrate the behavior of this property.
Thanks,
Ted
As usual, Ted, you have nailed this for me.
Thank you very much, once again, for your patience and your help.
Regards,
Tom