How to make a control dock in a wpf - c#

I'm trying to make my menu bar fill the screen horizontally like a menu bar should look. When I run the program the window is set to maximize already but the menu bar only fills half the screen on top. I'm not sure how to fix this. So just to be clear I'm trying to make my controls fit to appearance based on the size of the window.
Heres the code:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Royale" WindowStyle="ThreeDBorderWindow" SizeToContent="Manual" WindowState="Maximized" xmlns:my1="clr-namespace:System;assembly=mscorlib">
<Window.Resources>
<my1:Double x:Key="Width1">500</my1:Double>
</Window.Resources>
<Grid ShowGridLines="False" Width="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Menu Height="23" HorizontalAlignment="Left" Name="menu1" VerticalAlignment="Top" Width="503" IsMainMenu="True" Grid.ColumnSpan="2">
<MenuItem Header="File" HorizontalContentAlignment="Stretch">
<MenuItem Header="New">
<MenuItem Header="New Camper" />
</MenuItem>
</MenuItem>
<MenuItem Header="Edit" />
<MenuItem Header="View" />
<MenuItem Header="Add" />
</Menu>
</Grid>
</Window>

Using DockPanel:
http://www.wpftutorial.net/DockPanel.html
<DockPanel LastChildFill="True">
<Button Content="Dock=Top" DockPanel.Dock="Top"/>
<Button Content="Dock=Bottom" DockPanel.Dock="Bottom"/>
<Button Content="Dock=Left"/>
<Button Content="Dock=Right" DockPanel.Dock="Right"/>
<Button Content="LastChildFill=True"/>
</DockPanel>

The simple answer - set your menu to use Grid.ColumnSpan="3", since you have 3 columns.
However, I would recommend nesting your "main" grid inside of a DockPanel or a second Grid (with 2 rows). This way, as you add content (ie: add new columns to your grid), you won't have to constantly adjust your menu to compensate.

Related

Bind visibility of a LayoutAnchorable to a checkable MenuItem

C#, WPF. I would like to show/hide AvalonDock panels using checkable menu items. Although I could do this using _Click events I believe it would be good practice to use binding instead and that it should be possible to achieve this entirely using XAML.
I suspect that the answer should be along the lines of this one and have based my attempt on one of the answers given there.
This code compiles and runs, but there is no link between the menu being checked and the anchorable pane being visible. The key line is this:
<MenuItem Header="Panel" Name="PanelVisible" IsCheckable="True" IsChecked="{Binding Path=testAnchorable.IsVisible, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
How can I get this working?
<Window x:Class="TestAvalon.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:dock="http://schemas.xceed.com/wpf/xaml/avalondock"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Menu Height="18" HorizontalAlignment="Stretch" Name="menu1" VerticalAlignment="Top" Grid.Row="0">
<MenuItem Header="View">
<MenuItem Header="Panel" Name="PanelVisible" IsCheckable="True" IsChecked="{Binding Path=testAnchorable.IsVisible, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</MenuItem>
</MenuItem>
</Menu>
<dock:DockingManager x:Name = "Dockman" DataContext = "{Binding DockManagerViewModel}"
DocumentsSource = "{Binding Documents}" DockPanel.Dock = "Left" Grid.Row = "1" >
<dock:LayoutRoot x:Name = "_layoutRoot" >
<dock:LayoutPanel x:Name = "_layoutPanel" >
<dock:LayoutAnchorablePane DockWidth="400">
<dock:LayoutAnchorable x:Name ="testAnchorable" Title = "TEST PANE" IsSelected = "True">
<TextBlock Name="tb" Text="*****"/>
</dock:LayoutAnchorable >
</dock:LayoutAnchorablePane >
</dock:LayoutPanel >
</dock:LayoutRoot >
</dock:DockingManager>
</Grid>
</Grid>
This question now has a solution here:
Binding an AvalonDock LayoutAnchorable IsVisible property
(There are two answers given there and I think they both do the job.)

How can I drag and drop a list item to a image view (WPF)?

What I want is to drag and drop a list item from a listbox to an imageView in WPF.
So I have a listbox with some list items like: circle1, circle2 and an imageView with a picture.
Now I want to drag and drop one list item on this picture. And this list item is shown as a circle on this picture.
Is this possible?
My Main WPF with listbox and image:
<Window x:Class="MyProject.ControlCentre.UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CLock.ControlCentre.UI"
mc:Ignorable="d"
Title="MyProject - ControlCentre" Height="391" Width="767" Icon="/Images/MyIcon.ico">
<Grid Background="#FF2B2B2B" Height="376">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="0*"/>
</Grid.RowDefinitions>
<Menu x:Name="menuControlCentre" Margin="0,0,0,311" Background="#FF2B2B2B">
<MenuItem x:Name="menuItemControlCentre" Header="_File" Foreground="White">
<MenuItem x:Name="mItemLogInCC" Header="_LogIn" Foreground="Black"></MenuItem>
<MenuItem x:Name="mItemLoadImageCC" Header="_Load Image" Foreground="Black" Click="mItemLoadImageCC_Click"></MenuItem>
<MenuItem x:Name="meItemExitCC" Header="_Exit" Foreground="Black" Click="menueItemExitControlCentre_Click"></MenuItem>
</MenuItem>
</Menu>
<ListBox x:Name="lbxCircles" Margin="10,58,562,23" Background="White" SelectionChanged="lbxDoors_SelectionChanged"/>
<Label Content="Türen:" HorizontalAlignment="Left" Margin="10,32,0,0" VerticalAlignment="Top" Foreground="White" Height="26" Width="44"/>
<Image x:Name="imgPlanOfRoom" HorizontalAlignment="Left" Height="228" Margin="247,58,0,0" VerticalAlignment="Top" Width="487"/>
<Label Content="Plan of Room:" HorizontalAlignment="Left" Margin="247,35,0,0" VerticalAlignment="Top" Foreground="White"/>
</Grid>
I tried doing it with AllowDrop and stuff but it didn't work. I don't know how to implement the function that the list item converts into a circle and gets dropped on an imageView.
I hope someone can help me.

WPF Page->Canvas->TabControl->TabItem->Grid->DataGrid not showing vertical scrollbars

OK, I too, have come across the "vertical scrollbar not showing" problem, the suggested solutions either don't work or aren't applicable in this case.
The desire is to show not one, but two data grids, side by side, each with it's own data source on an application that will respond correctly to user resizing, meaning that the grids will expand and contract as expected. The grids should be "anchored" and render accordingly (oh, how I miss the days of WinForms and actual, simple anchoring!).
The first grid will normally show insufficient rows to trigger a vertical scrollbar, that's OK.
The second datagrids' content is based on the selected row of the first datagrid, meaning when a user selects a row in the first datagrid (column 0), an SQL statement is executed and the result shows in the other datagrid (the one in column 1).
What does happen is that the second grids' content, if larger than the displayed size, will continue to render (out of sight) pushing the pages container items (a status bar at the bottom, not shown in the code) to one side and continue to render right off the applications boundaries (not visible, but the grid behaves as if it has infinite room to display).
What I don't get is a nice, paged grid with a vertical scroll bar.
I'm using MVVMLight as the toolkit and the corresponding ViewModel works as designed. The data isn't the issue, just the rendering.
I'm pretty sure the solution is quite simple, I just don't have the xaml experience yet (I'm a newbie with this) to figure it out. I've tried enclosing the grids in various other containers (DockPanel, StackPanel with orientation=Horizontal, etc.) but just can't seem to get it right. I even tried binding the row height to the tab control actual height - fail.
So...a little help with a tutorial explanation would be greatly appreciated!
Here is the complete xaml (save that I have removed extraneous tab pages) for the page:
<Page x:Class="GetSchemaExplorerMsSqlSvr.DbMetaDataPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:GetSchemaExplorerMsSqlSvr"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:command="http://www.galasoft.ch/mvvmlight"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="500"
Height="Auto"
Width="Auto"
Title="DbMetaDataPage"
x:Name="pgDbMetaDataPage"
Background="{StaticResource YellowBackground}"
DataContext="{Binding MainWindowVM, Source={StaticResource Locator}}"
>
<Canvas>
<TabControl x:Name="tcDbMetaData" Height="Auto" Width="Auto">
<TabItem x:Name="tiDbMetaData" Header="Get Schema" VerticalAlignment="Stretch">
<Grid Margin="1,1,1,1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<DataGrid
Grid.Column="0"
x:Name="dgDbMetaData"
ItemsSource="{Binding Path=GetSchemaMetaData, Mode=OneWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
IsReadOnly="True"
SelectedItem="{Binding Path=SelectedMetaDataItem, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
/>
<DataGrid
Grid.Column="1"
ItemsSource="{Binding Path=MetaDataCollectionInfo, Mode=OneWay}"
IsReadOnly="True"
VerticalScrollBarVisibility="Auto"
/>
</Grid>
</TabItem>
</TabControl>
</Canvas>
</Page>
That is happening because you are setting your TabControl as a Child of a Canvas. It is used to set abolute positioning of its Child elements. Since you don't need to set abolute positions, you should just remove your Canvas and set the content of your Page to be your TabControl directly.
From MSDN:
Child elements of a Canvas are always given the full size that they desire. As a result, vertical alignment and horizontal alignment have no effect inside a Canvas.
(https://msdn.microsoft.com/en-us/library/system.windows.controls.canvas%28v=vs.110%29.aspx)
Your code would then be:
<Page...>
<TabControl ...>
<TabItem ...>
<Grid ...>
<DataGrid Grid.Column="0".../>
<DataGrid Grid.Column="1" .../>
</Grid>
</TabItem>
</TabControl>
</Page>
As was pointed about above, removing the Canvas element solved the problem. The altered xaml is posted below just for the sake of reference. The result isn't pretty, but right now I'm looking for functional and this does the trick.
<Page x:Class="GetSchemaExplorerMsSqlSvr.DbMetaDataPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:GetSchemaExplorerMsSqlSvr"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:command="http://www.galasoft.ch/mvvmlight"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="500"
Height="Auto"
Width="Auto"
Title="DbMetaDataPage"
x:Name="pgDbMetaDataPage"
Background="{StaticResource YellowBackground}"
DataContext="{Binding MainWindowVM, Source={StaticResource Locator}}"
>
<TabControl x:Name="tcDbMetaData" Height="Auto" Width="Auto">
<TabItem x:Name="tiDbMetaData" Header="Get Schema" VerticalAlignment="Stretch">
<DockPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid DockPanel.Dock="Top" Background="{StaticResource YellowBackground}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition MaxHeight="40"/>
</Grid.RowDefinitions>
<DataGrid
Grid.Row="0"
Grid.Column="0"
x:Name="dgDbMetaData"
ItemsSource="{Binding Path=GetSchemaMetaData, Mode=OneWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
IsReadOnly="True"
SelectedItem="{Binding Path=SelectedMetaDataItem, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
/>
<DataGrid
Grid.Row="0"
Grid.Column="1"
ItemsSource="{Binding Path=MetaDataCollectionInfo, Mode=OneWay}"
IsReadOnly="True"
VerticalScrollBarVisibility="Auto"
/>
<Button Grid.Column="0" Grid.Row="1" MaxHeight="30" Margin="5, 5, 5, 5" Content="Fetch MetaData"/>
</Grid>
</DockPanel>
</TabItem>
<TabItem Header="Tables">
<Grid Background="#FFE5E5E5"/>
</TabItem>
<TabItem Header="Views">
<Grid Background="#FFE5E5E5"/>
</TabItem>
<TabItem Header="Stored Procedures">
<Grid Background="#FFE5E5E5"/>
</TabItem>
<TabItem Header="Functions">
<Grid Background="#FFE5E5E5"/>
</TabItem>
</TabControl>
</Page>

How to make controls fill the container in WPF?

Below is my xaml code :
<Window x:Class="ScoresBank.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<DockPanel LastChildFill="True">
<WrapPanel DockPanel.Dock="Top">
<ToolBar Height="25"></ToolBar>
</WrapPanel>
<WrapPanel DockPanel.Dock="Bottom">
<StatusBar Name="stbBottom" Height="25"
BorderThickness="2"
BorderBrush="Black">Example</StatusBar>
</WrapPanel>
<StackPanel DockPanel.Dock="Left">
<DockPanel LastChildFill="True">
<WrapPanel DockPanel.Dock="Top">
<Button Name="btnBrowseTags">TAGS</Button>
<Button Name="btnBrowseTitles">TITLES</Button>
</WrapPanel>
<ComboBox DockPanel.Dock="Top" Name="cbxCategory">
Example
</ComboBox>
<WrapPanel DockPanel.Dock="Bottom">
<TextBox Name="txtKeyword"></TextBox>
<Button Name="btnFind">Find</Button>
</WrapPanel>
<ListBox Name="lbxBrowse">
</ListBox>
</DockPanel>
</StackPanel>
<StackPanel DockPanel.Dock="Right">
<Button>Example</Button>
</StackPanel>
<Canvas>
</Canvas>
</DockPanel>
And this is my current layout view :
So, what I mean with filling the container are :
Making lbxBrowse to fill the mid-space of the DockPanel inside the left StackPanel.
Making txtKeyword to fill the WrapPanel.
Making stbBottom to fill the WrapPanel.
What I've tried :
It seems i've put them in a DockPanel with LastChildFill="True". But it seems doesn't work.
I don't know about this, since it's not possible to put it into a DockPanel first.
I don't know anything about this.
I don't use fixed size, since I need them to keep neat even when resized in multiple screen resolution. The fixed size on ToolBar and StatusBar seems required, otherwise, the text will be unseen.
P.S. If possible, I prefer the solution to be XAML code, rather than the C# code. Otherwise, C# code is fine too.
Thank you.
You should use a Grid. It is more easier to configure. Here is an example (I don't know exactly how you want to setup your layout).
<Window x:Class="SampleWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="400" Width="600">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Margin="5" Content="TAGS"
Grid.Column="0" Grid.Row="0" />
<Button Margin="5" Content="TITLES"
Grid.Column="1" Grid.Row="0" />
<Button Margin="5" Content="EXAMPLES"
Grid.Column="2" Grid.Row="0"
HorizontalAlignment="Right"/>
<ComboBox Margin="5"
Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" />
<ListBox Margin="5"
Grid.Column="2" Grid.Row="1" Grid.RowSpan="2" />
<Button Margin="5" Content="EXAMPLE"
Grid.Column="2" Grid.Row="3" HorizontalAlignment="Left" />
</Grid>
</Window>
And the result:
With a grid you can set the height and the width of the columns and rows to a specific value (in points, pixels, cm, etc.), to column content (Auto) or proportional to the grid (with *).
Instead of using a StackPanel and DockPanel you can use Grid and set Grid.ColumnDefinitions and Grid.RowDefinitions. You can specify directly each row Height and each column Width. It's easier to use and it automaticly fit to content and container.

How to make items in a DockPanel expand to fit all available space in WPF?

I have a StackPanel containing a StackPanel and some other items. The first StackPanel has a vertical orientation, the the inner one has a horizontal orientation. The inner one has a TreeView and a ListView, I would like them to expand and fit the width of the window, which I set by the window and allow the user to change. I would also like the outer StackPanel to fit the height of the window. How do I do this?
Edit:
I've converted to using a DockPanel, and I've set the DockPanel.Dock properties correctly in each of the elements, and have disabled LastChildFill in both of the dockpanels, the layout still does not stretch.
The Code:
<Window x:Class="Clippy.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="400" Width="600" MinHeight="400" MinWidth="600" Loaded="Window_Loaded" SizeChanged="Window_SizeChanged">
<DockPanel Name="wrapperDockPanel" LastChildFill="False">
<Menu Height="22" Name="mainMenu" Width="Auto" DockPanel.Dock="Top" />
<ToolBar Height="26" Name="mainToolBar" Width="Auto" DockPanel.Dock="Top" />
<DockPanel Height="Auto" Name="contentDockPanel" DockPanel.Dock="Top" LastChildFill="False">
<TreeView Name="categoryTreeView" />
<ListView Name="clipListView" />
</DockPanel>
<StatusBar Height="23" Name="mainStatusBar" DockPanel.Dock="Top" />
</DockPanel>
</Window>
Use a DockPanel instead. StackPanel explicitly doesn't care about visible space, whereas DockPanel does all of it's size calculation based on available space.
Update:
In addition, in my experience, putting the body of the window into a View, and only having the View in the Window makes for a better Auto Size experience.
For some reason putting all of the children directly into the Window seems to not auto size very well.
Update 2:
I would remove the explicit DockPanel.Dock attribute from the element that you want to stretch (fill) the unused space.
This should do it - I set it up so that the TreeView and the ListView shared the main view 50/50; if you don't want that, set it to 'Auto' and '*' or something. Use "LastChildFill" to your advantage!
<Window x:Class="Clippy.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="400" Width="600" MinHeight="400" MinWidth="600" Loaded="Window_Loaded" SizeChanged="Window_SizeChanged">
<DockPanel LastChildFill="True">
<Menu Width="Auto" DockPanel.Dock="Top" />
<ToolBar Width="Auto" DockPanel.Dock="Top" />
<StatusBar DockPanel.Dock="Bottom" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.5*" />
<RowDefinition Height="0.5*" />
</Grid.RowDefinitions>
<TreeView Name="categoryTreeView" Grid.Row="0" />
<ListView Name="clipListView" Grid.Row="1" />
</Grid>
</DockPanel>
</Window>
Set width and height properties to "auto"

Categories