WPF Show/Hide a set of controls - wpf

I'm working on a WPF desktop application. The MainWindow is a maximized window that has a menu with few menu items. I would like to display few controls within a groupbox on the center of the window. This groupbox contains controls depending on the menu item clicked. So the size of the groupbox should not be static. Is this possible?
Thanks

Try to define your XAML like this
<Window x:Class="WpfApplication1.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" WindowState="Maximized">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel>
<Button Content="Click" Height="30" Width="160"/>
<Button Content="Click" Height="30" Width="160"/>
<!--<Button Content="Click" Height="30" Width="160"/>-->
</StackPanel>
</GroupBox>
<Grid Grid.Row="1">
<TextBlock FontSize="26" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" Text="MainUserWork Panel"/>
</Grid>
</Grid>

Related

WPF Forms Integration - A Problem with Grid

I am doing a feasibility study to find out whether and how we can integrate a Forms application into a WPF project.
I started with a simple example and immediately encountered a problem (here is the code):
<Window x:Class="TestFormsIntegration.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:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:local="clr-namespace:TestFormsIntegration"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="Menue Bar" HorizontalContentAlignment="Center" Background="BlanchedAlmond" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<ScrollViewer x:Name="scrollViewer" Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="200" />
<RowDefinition Height="200" />
<RowDefinition Height="200" />
</Grid.RowDefinitions>
<WindowsFormsHost Grid.Row="0" HorizontalAlignment="Center" Height="190" VerticalAlignment="Center" Width="250">
<wf:Button Text="Button 0" Height="180" Width="200" BackColor="Gray" />
</WindowsFormsHost>
<WindowsFormsHost Grid.Row="1" HorizontalAlignment="Center" Height="190" VerticalAlignment="Center" Width="250">
<wf:Button Text="Button 1" Height="180" Width="200" BackColor="Gray"/>
</WindowsFormsHost>
<WindowsFormsHost Grid.Row="2" HorizontalAlignment="Center" Height="190" VerticalAlignment="Center" Width="250">
<wf:Button Text="Button 2" Height="180" Width="200" BackColor="Gray" />
</WindowsFormsHost>
<WindowsFormsHost Grid.Row="3" HorizontalAlignment="Center" Height="190" VerticalAlignment="Center" Width="250">
<wf:Button Text="Button 3" Height="180" Width="200" BackColor="Gray" />
</WindowsFormsHost>
</Grid>
</ScrollViewer>
<Label Grid.Row="2" Content="Status Bar" HorizontalContentAlignment="Center" Background="Wheat" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Grid>
</Window>
In a grid with 4 rows I place 4 forms buttons. When I run the code, the inner grid crosses the boundaries and overwrites the labels at the top and bottom (indicating Menu and Status Bar) and takes up the height of the entire window.
Does anyone know this behaviour and how to fix it?
Hint: Try a larger value for height (you have Height="450"), because the sum of the height of your elements is just higher (200 * 4) and don't forget the labels.
I have found the solution here:
WindowsFormsHost ZOrder
Here I read:
In a WPF user interface, you can change the z-order of elements to control overlapping behavior. A hosted Windows Forms control is drawn in a separate HWND, so it is always drawn on top of WPF elements.
But this article also contains an answer with a solution!
You can do a little trick. When you declare an WindowsFormsHost, it's parent is first HWND component. Usually it's root window. So, clip area for controls is whole window.
But there's a way to create "intermediate" HWND item to clip WinForms area over ScrollViewer. Just place another WindowsFormsHost with ElementHost.
Thank you for your answer, ds1709.

Textbox does not show a verticalscrollbar

<Window
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"
mc:Ignorable="d" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="350" Width="550" MinHeight="350">
<DockPanel Background="BlanchedAlmond">
<DataGrid Background="YellowGreen" DockPanel.Dock="Top" MinHeight="100">
</DataGrid>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" FlowDirection="RightToLeft" Margin="10" Background="YellowGreen">
<Button HorizontalAlignment="Right" Click="Button1Add_Click" Margin="5,0">Add text 1</Button>
<Button HorizontalAlignment="Right" Click="Button2Add_Click">Add text 2</Button>
<Button HorizontalAlignment="Right" Click="Button1_Click" Margin="5,0">Toggle textbox 1</Button>
<Button HorizontalAlignment="Right" Click="Button2_Click">Toggle textbox 2</Button>
</StackPanel>
<Grid Background="Red">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox x:Name="TextBox1" Grid.Row="0" Background="AliceBlue" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">Test 1</TextBox>
<TextBox x:Name="TextBox2" Grid.Row="1" Background="AliceBlue" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">Test 2</TextBox>
</Grid>
</DockPanel>
</Window>
In the example above I am trying to achieve that the two textboxes in the middle just fill the available space between the top datagrid and the bottom stackpanel with buttons.
They have to divide that space between them depending on their text-content and their visibility.
Both properties can change by databindings, I simulated that with the click events.
But when the space is filled up they have to show a vertical scrollbar when needed.
The code sample above is not good. When I add text to a textbox, the grid-row becomes larger but disappears from the visible region, no scroll bar.
EDIT: I ended up with:
<ScrollViewer Background="AliceBlue" VerticalScrollBarVisibility="Auto">
<StackPanel Orientation="Vertical">
<Label x:Name="Label1" Margin="0,6,0,0">Test 1:</Label>
<TextBox x:Name="TextBox1" Padding="0,6"></TextBox>
<Label x:Name="Label2" Margin="0,6,0,0">Test 2:</Label>
<TextBox x:Name="TextBox2" Padding="0,6" ></TextBox>
</StackPanel>
</ScrollViewer>
You need to add a ScrollViewer in your XAML around the content.
ScrollViewer on MSDN
<ScrollViewer>
Content
</ScrollViewer>

How to call a Usercontrol from another in same window in WPF ?

I have two UserControls in my project's MainWindow. In MainWindow I call the first UserControl whose content is a Button and put this FirstControl in a Grid. How can I call the second UserControl when I click on the button in FirstUserControl in MainWindow?
First UserControl :
<UserControl x:Class="BenashManage.UserControl.ButtonUserControl"
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"
Height="auto" Width="auto" RenderTransformOrigin="0,0">
<Grid>
<Border x:Name="BorderAddEdit" BorderBrush="{DynamicResource BorderBrush}" BorderThickness="5,5,5,5" CornerRadius="9,9,9,9" Background="{x:Null}">
<Grid Margin="0.2,0.2,5.4,4.2">
<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<Button Content="one" TextBlock.Foreground="White" Grid.Row="1" Margin="9,9,9,9" Height="28" TextBlock.FontSize="15" Name="btn_MartyMang" Click="click_Marty"/>
</Grid>
</Border>
</Grid>
</UserControl>
Second UserControl:
<UserControl x:Class="BenashManage.UserControl.InjuredUserControl"
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"
Height="auto" Width="auto"
mc:Ignorable="d" RenderTransformOrigin="0,0" FontFamily="Arial" FontSize="14" TextBlock.Foreground="White">
<Grid VerticalAlignment="Top" Height="auto" Width="360" HorizontalAlignment="Right">
<Border x:Name="BorderAddEdit" Margin="6,2,6,6" BorderThickness="5,5,5,5" CornerRadius="9,9,9,9" Background="{x:Null}">
<Grid VerticalAlignment="Center" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" MinHeight="20.8"/>
</Grid.ColumnDefinitions>
<TextBlock TextWrapping="Wrap" Text=":jjj" Grid.Column="1" Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,4,-0.4,3"/>
<TextBox Grid.Row="6" TextAlignment="Right" VerticalAlignment="Center" Margin="3,2.8,2.2,2.2" />
</Grid>
</Border>
</Grid>
</UserControl>
MainWindow:
<Window x:Class="BenashManage.MartyrManage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:BenashManage.UserControl"
Title="MartyrManage" Height="550" Width="550" Style="{DynamicResource ModalWindowStyle}" Loaded="Window_Loaded_1">
<Window.CommandBindings>
<CommandBinding Command="Close"
Executed="CloseCommand_Executed"/>
</Window.CommandBindings>
<Grid >
<Grid Margin="179,10,10.4,10" HorizontalAlignment="Center" VerticalAlignment="Center"
*******
Height="456" Width="357" Name="MoveToUserControl" ></Grid>
<Grid Margin="10,71,372.4,67" HorizontalAlignment="Center" VerticalAlignment="Center" Height="338" Width="auto" Name="ButtonManage" >
<controls:FirstUserControl Margin="0,0,0,92">
</controls:FirstUserControl>
</Grid>
</Grid>
</Window>
There are a couple of ways you can do this:
1) Get the parent of the UserControl and then get its children.
(((control1).Parent as Panel).Children[1] as UserControl)
2) Raise an event in the one UserControl which is handled by MainWindow to call the function in the other UserControl.

Setting the cursor in a WPF documentViewer

I am creating a WPF document viewer that will zoom in to a page when it is double clicked on. To this end I am trying to get the cursor to turn into a hand when over a page in the document viewer, and an arrow when elsewhere.
I have my xaml set up like so
<UserControl x:Class="WPFXPSViewerControl.XPSControl"
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:UI="clr-namespace:Bluewire.Epro.UI;assembly=EproClientCore"
xmlns:System="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d"
Loaded="Window_Loaded"
Height="1200" MouseDoubleClick="Double_Click">
<Grid Grid.Row="2" Grid.Column="2" Cursor="Hand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="20" Cursor="Arrow"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<DocumentViewer Name="document" Grid.ColumnSpan="2" Cursor="Arrow">
</DocumentViewer>
<Button Width="200" Name="btnZoomIn" Grid.Row="1" Grid.Column="0" Cursor="Hand" Click="btnZoomIn_Click">Zoom In</Button>
<Button Width="200" Name="btnZoomOut" Grid.Row="1" Grid.Column="1" Cursor="Hand" Click="btnZoomOut_Click">Zoom Out</Button>
</Grid>
</UserControl>
However, I cannot seem to change the cursor when it is over a page from its default setting of a text cursor.
You could try the following statements:
Cursor="Arrow" ForceCursor="True"

Why the height is incorrect?

I have a simple WPF form with next XAML
<Window x:Class="ReikartzDataConverter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="650" Width="800">
<Grid Width="780" Height="650">
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="500"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="Process information" Height="28" HorizontalAlignment="Left" Margin="0,20,0,0" Name="label1" VerticalAlignment="Top" Width="235" />
<DataGrid Grid.Row="1" Width="780" Height="500" Name="paysTable">
</DataGrid>
<Label Grid.Row="2" Height="28" Name="lblError" VerticalAlignment="Top" Visibility="Hidden" Foreground="OrangeRed" FontWeight="Bold" FontSize="12" />
<Button Grid.Row="3" Content="Quit" Height="23" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
<Button Grid.Row="3" Content="Start" Height="23" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click" />
</Grid>
</Window>
Why my 2 buttons from Grid.Row="3" are partially located out of the visible part of the window?
My window has the height="650" and my Grid also has the Height="650"
I have 4 Rows: 50, 50, 500, 50. So the last row must be located inside the window. Why is not so?
The Window Height of 650 also includes the 'chrome', i.e. the bar at the top of the window with the minimize, maximize buttons. It is a much better approach to create a layout which does not rely on a specific height. In your case, I would make the row that contains your grid auto-sized:
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
Then you can remove the height / width from your Grid, and all your other UI elements, just let the grid dictate the size of its children.
#ColinE's answer is the right approach in that you should adopt a "fluid" layout in WPF, but if you really want a fixed height for your content and you need the window to be the right size, you can use the SizeToContent property:
<Window x:Class="ReikartzDataConverter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Width="800"
SizeToContent="Height">
<Grid Width="780" Height="650">
...
</Grid>
</Window>
Setting SizeToContent to "Height" will make the window resize vertically so that its contents fit. Don't forget to remove the Height property from the Window declaration.

Resources