Matt
Matt

Reputation: 99

Dock and Anchor in WPF

I am coming from a WinForms background and am starting to learn WPF. I've gone through a set of tutorials at Pluralsight, but am having a little difficulty with handling resizing.

When resizing, my textboxes don't seem to be "anchoring" in the way I would want. I'm including the xaml below with notes in it as to the behavior I am looking for. Any feedback regarding best practices would be very much appreciated. The code just "feels" a little awkward to me, but I'm not sure if that is because it's just new to me, or if there are easier/better ways of doing what I am attempting.

To get an idea of what things look like without needing to load the XAML below - here are before and after resizing the form screenshots. Before Resize http://dboasis.com/screenshots/beforeresize.jpg After Resize http://dboasis.com/screenshots/afterresize.jpg

I'm hoping for suggestions both how to handle the resize issues, as well as best practices after seeing how I've attempted to do it in the XAML.

Also - the xaml does implement DevExpress controls - if anyone wants me to redo the form and not use 3rd party controls so they more easily make suggestions, I am happy to do so.

<dx:DXWindow
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
    xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars"
    xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" x:Class="DXTemplateSandbox.MainWindow"
    Title="MainWindow" Height="437" Width="641">
<Grid>
    <dx:DXTabControl x:Name="tabcntMainTab">
        <dx:DXTabItem x:Name="tabUserList" Header="User List">
            <Grid Background="Transparent">

                <Grid.RowDefinitions>
                    <RowDefinition x:Name="SelectLabel" Height="30" />
                    <RowDefinition x:Name="OpenDataFile" Height="34" />
                    <RowDefinition x:Name="DataGridLayoutRow" Height="185*" />
                    <RowDefinition x:Name="AppPrefsInfo" Height="110" />
                </Grid.RowDefinitions>
                <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="10,0">
                    <!-- 
                    The DataFileLocation not resizing the width.  How do I instead lock the vertical size, but allow width to
                    resize with form?
                    -->
                    <TextBox Name="DataFileLocation" Width="419" Margin="0,5" HorizontalAlignment="Stretch" />

                    <!--
                    How do I get the SelectData button stay immediately to the right of the DatFileLocation textbox when resizing?
                    -->
                    <Button Name="SelectData" Content="..." Width="40" Margin="5" Click="SelectData_Click"/>
                    <DockPanel>
                        <!-- I would like the "Go" button to stay anchored to the right when resizing. -->
                        <Button x:Name="GoButton" 
                                Content="Go" 
                                Width="66" 
                                DockPanel.Dock="Right"
                                HorizontalAlignment="Right"
                                VerticalAlignment="Top"
                                Margin="50,5,5,5" 
                                Click="GoButton_Click" />
                    </DockPanel>

                </StackPanel>

                <!--
                -->
                <dxg:GridControl Grid.Row="2" Margin="5" >
                    <dxg:GridControl.View>
                        <dxg:TableView ShowGroupPanel="False"/>
                    </dxg:GridControl.View>
                </dxg:GridControl>

                <Label Content="Select Data File" HorizontalAlignment="Left" Margin="5,5,0,0" VerticalAlignment="Top" Height="26" Grid.RowSpan="2" Width="91"/>

                <!-- 
                Is using a grid inside a parent grid cell the best way of doing this?  I'm using stackpanels in each of the rows in the
                child grid.  Is there a better way of doing this?  
                -->
                <Grid x:Name="AppPrefsGrid" Grid.Row="3" >
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <!--
                    Ideally I would like the text boxes to grow and shrink at the same rate as form is resized, and leave the labels the same width.  I don't know
                    if this is practical however.
                    -->
                    <StackPanel Grid.Row="0" Orientation="Horizontal">
                        <Label Content="Registration Name:" Width="112" Margin="5"/>
                        <TextBox Name="RegNameTextBox" Width="175" Margin="5" IsEnabled="False"/>
                        <Label Content="Install Date:" Width="84" Margin="10,5,5,5"/>
                        <TextBox Name="InstallDateTextBox" Width="175" Margin="5" IsEnabled="False"/>
                    </StackPanel>
                    <StackPanel Grid.Row="1" Orientation="Horizontal">
                        <Label Content="Registration Number:" Width="112" Margin="5"/>
                        <TextBox Name="RegNumberTextBox" Width="175" Margin="5" IsEnabled="False"/>
                        <Label Content="Data File Version:" Width="84" Margin="10,5,5,5"/>
                        <TextBox Name="DataVersionTextBox" Width="175" Margin="5" IsEnabled="False"/>
                    </StackPanel>
                    <StackPanel Grid.Row="2" Orientation="Horizontal">
                        <Label Content="Edition Code:" Width="112" Margin="5"/>
                        <TextBox Name="EditionCodeTextBox" Width="175" Margin="5" IsEnabled="False"/>
                        <Label Content="User Count:" Width="84" Margin="10,5,5,5"/>
                        <TextBox Name="UserCountTextBox" Width="175" Margin="5" IsEnabled="False"/>
                    </StackPanel>


                </Grid>

            </Grid>

        </dx:DXTabItem>
        <dx:DXTabItem x:Name="tabKeyGen" Header="Key Generator"/>
    </dx:DXTabControl>
</Grid>

Upvotes: 3

Views: 15809

Answers (1)

Rachel
Rachel

Reputation: 132548

You have multiple problems here that appear to be because you are not using the correct layout panel for your controls.

By default, the size of a control is based on the behavior of the parent.

For example, items placed inside a Grid will stretch to fill all available space given to them inside the Grid Cell. If the Grid Row/Column definition has a Height/Width set to Auto it means it will draw the control at whatever size the control wants. If it's set to a fixed size such as 100, then it will draw the control at that size. If it's set to a * size, it will draw the control using a percentage of the remaining space.

This behavior can be overridden by properties on the control itself, such as HorizontalAlignment and VerticalAlignment, or setting properties such as the Height, Width, and Margin.

So, to address some of your specific problems, start by removing those stack panels hosting your label/textbox combinations and replace them with a proper 3x4 Grid. Put your labels in columns 0 and 2 and give that ColumnDefinition a fixed size. Put your TextBoxes in columns 1 and 3, and leave them as a * size. Remember, a * size is a percentage, so 2* in one column and 3* in another column will mean there are 5* available total, and column 1 will take up 2/5 of the space while column2 will take up 3/5th of the space.

To get your DataFileLocation to resize as the form resizes, simply remove the Width property and let it size to whatever size the grid cell is.

To get the SelectData button to stay docked to the right of the SelectData textbox, place both in a DockPanel. Dock the Button to the Right side, and allow the TextBox to fill all remaining space. You will have to set the TabIndex if you want the tab key to cycle through them as expected.

<DockPanel>
    <Button DockPanel.Dock="Right" ... />
    <TextBox ... />
</DockPanel>

Start with that, and see how it looks. Your RowDefinition for your parent grid looks correct (other than the fact your 3rd row height should be "*" and not "184*"), and it should mean your DevExpress control should stretch/shrink to fill all remaining vertical space.

Upvotes: 6

Related Questions