In my window, two panels are separated by grid splitter. Splitter functionality works properly. When bottom panel closes, I want top panel to occupy total screen space (similar to visual studio IDE) however when I close the panel, it leaves the blank space. Code which demonstrates this problem is given below :
XAML
<Window x:Class="WpfApp1.Window1"
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:WpfApp1"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800" WindowState="Maximized">
<Grid x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel x:Name="panel1" Grid.Row="0" Background="Bisque" Margin="3" Orientation="Vertical">
<Button Height="50" Content="Button 1" Margin="5"/>
<Button Height="50" Content="Button 2" Margin="5"/>
<Button Height="50" Content="Button 3" Margin="5"/>
</StackPanel>
<GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ShowsPreview="True" ResizeDirection="Rows"/>
<StackPanel x:Name="panel2" Grid.Row="2" Background="AliceBlue" Margin="3" Orientation="Vertical">
<Button Content="X" HorizontalAlignment="Right" VerticalAlignment="Top" Click="Button_Click"/>
<Button Height="50" Content="Button 4" Margin="5"/>
<Button Height="50" Content="Button 5" Margin="5"/>
<Button Height="50" Content="Button 6" Margin="5"/>
</StackPanel>
</Grid>
</Window>
Code behind
using System.Windows;
namespace WpfApp1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
grid.Children.Remove(panel2);
}
}
}
Can anyone suggest any approach or solution to achieve my requirement i.e. upon closing bottom panel, top panel occupies all available space?
Thanks
You could start with these heights:
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
...and simply set the Height of the last one to Auto when you remove the StackPanel:
private void Button_Click(object sender, RoutedEventArgs e)
{
grid.Children.Remove(panel2);
grid.RowDefinitions[Grid.GetRow(panel2)].Height = new GridLength(1, GridUnitType.Auto);
}
Related
I'm trying to create a custom popup window in WPF, but I can't seem to do it without a there being a black "drop shadow" around it. I'm using ContentControl for the body of it so that I can change the body for different popups.
I can remove the "shadow" by removing SizeToContent="WidthAndHeight", but then I don't have a window that adapts to it's content.
Here's the xaml
<Window x:Class="PriceFinding.Utility.Dialogs.Service.DialogWindow"
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PriceFinding.Utility.Dialogs.Service"
mc:Ignorable="d"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen"
MinHeight="300" MinWidth="800"
Background="{StaticResource BrushPrimary}"
>
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="50"/>
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" WindowChrome.IsHitTestVisibleInChrome="True" VerticalAlignment="Top" Background="{StaticResource BrushPrimaryDark}" Name="TitleBar" Height="35">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Image Source = "pf.ico" Height="20" Width="20" Margin="5,0" />
<Label Content="{Binding Title}" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="14"/>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,5,0">
<Button
x:Name="MinButton"
Height="35" Width="35" Padding="0"
Command="{Binding MinimizeButton.MinimizeCommand}">
</Button>
<Button
x:Name="MaxButton"
Height="35" Width="35" Padding="0"
HorizontalAlignment="Left"
Command="{Binding MaximizeButton.MaximizeCommand}">
</Button>
<Button
x:Name="CloseButton"
Height="35" Width="35" Padding="0"
HorizontalAlignment="Right"
Command="{Binding CloseButton.CloseCommand}">
</Button>
</StackPanel>
</Grid>
<ContentControl Grid.Row="1" x:Name="ContentPresenter" Content="{Binding}"></ContentControl>
</Grid>
How can I get around this?
Here (or here, for the more daring) is a workaround!
This is quite a weird problem, but, indeed, running an event when the content is rendered:
ContentRendered="Window_OnContentRendered"
like so:
private void Window_OnContentRendered(object sender, EventArgs e)
{
InvalidateVisual();
}
InvalidateVisual does not remeasure content of window. Also no need to change the chrome.
This helped me:
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
// Content of window may be black in case of SizeToContent is set.
// This eliminates the problem.
// Do not use InvalidateVisual because it may implicitly break your markup.
InvalidateMeasure();
}
You can set the GlassFrameThickness to zero:
<WindowChrome GlassFrameThickness="0"
CaptionHeight="0" />
And that should remove the drop shadow effect and it will also allow you to use the CornerRadius effect if you were interested.
This is caused by a bug in WPF.
See https://social.msdn.microsoft.com/Forums/vstudio/en-US/f51ba061-69e2-4c85-b77a-41307423c2bf/sizetocontentheight-windowstylenone-resizemodenoresize-weirdness?forum=wpf
For a workaround, you can refresh the view. InvalidateVisual did not work for me.
You can attach an event handler to the window like so:
Background="{StaticResource BrushPrimary}" Activated="Window_Activated" StateChanged="Window_Activated"
Then, in the code behind:
private void Window_Activated(object sender, EventArgs e)
{
this.SizeToContent = SizeToContent.Manual;
this.SizeToContent = SizeToContent.WidthAndHeight;
}
I would like to have Grid with two rows. Rows should take only space needed for them (thats why Grid VerticalAlignment is set to Top). When there is not enough space to show both rows scrollbars should appear. I have tried different combinations with Auto, *, MinHeight etc. but without success.
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WpfApplication5"
Title="MainWindow" Height="388" Width="525" FontSize="25">
<Grid VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Border Height="100" Background="Red" >
<StackPanel>
<TextBlock Text="1"/>
<TextBlock Text="2"/>
<TextBlock Text="3"/>
<TextBlock Text="4"/>
</StackPanel>
</Border>
</ScrollViewer>
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Border Background="Green" >
<StackPanel>
<TextBlock Text="1" />
<TextBlock Text="2"/>
<TextBlock Text="3"/>
<TextBlock Text="4"/>
<TextBlock Text="5"/>
<TextBlock Text="6"/>
<TextBlock Text="7"/>
<TextBlock Text="8"/>
<TextBlock Text="9"/>
<TextBlock Text="10"/>
</StackPanel>
</Border>
</ScrollViewer>
</Grid>
</Window>
EDIT Check this image. Why there is not 4 in first row, why there is empty space at bottom.
<Border Height="100" Background="Red" >
Height="100" makes the content in the 1st row no.4 to hide inside. Also, you have made the rows in to two equal parts, however the content is not equal which leaves empty space at the bottom of the window.
There is no solution out of the box, because it depends on what ratio you want between the two scrollviewers, in my example I choose 50/50:
<Window x:Class="WpfApplication.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:WpfApplication"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Canvas x:Name="OverallCanvas" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid x:Name="OverallGrid" Width="{Binding ElementName=OverallCanvas, Path=ActualWidth}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollViewer x:Name="Scroll1" Grid.Row="0" VerticalScrollBarVisibility="Auto">
<StackPanel x:Name="Control1" Background="Red">
<TextBlock Text="1.1"/>
<TextBlock Text="1.2"/>
<TextBlock Text="1.3"/>
<TextBlock Text="1.4"/>
<TextBlock Text="1.5"/>
</StackPanel>
</ScrollViewer>
<ScrollViewer x:Name="Scroll2" Grid.Row="1" VerticalScrollBarVisibility="Auto">
<StackPanel x:Name="Control2" Background="Green">
<TextBlock Text="2.1"/>
<TextBlock Text="2.2"/>
<TextBlock Text="2.3"/>
<TextBlock Text="2.4"/>
<TextBlock Text="2.5"/>
<TextBlock Text="2.6"/>
<TextBlock Text="2.7"/>
<TextBlock Text="2.8"/>
<TextBlock Text="2.9"/>
<TextBlock Text="2.10"/>
</StackPanel>
</ScrollViewer>
</Grid>
</Canvas>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.SizeChanged += MainWindow_SizeChanged;
Control1.SizeChanged += MainWindow_SizeChanged;
Control2.SizeChanged += MainWindow_SizeChanged;
}
private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateScrollHeight();
}
private void UpdateScrollHeight()
{
double overallHeight = OverallCanvas.ActualHeight;
double c1Height = Control1.ActualHeight + Control1.Margin.Top + Control1.Margin.Bottom;
double c2Height = Control2.ActualHeight + Control2.Margin.Top + Control2.Margin.Bottom;
if (overallHeight - c1Height - c2Height < 0)
{
double halfHeight = overallHeight / 2;
double c1Additional = Math.Max(0, halfHeight - c2Height);
double c2Additional = Math.Max(0, halfHeight - c1Height);
Scroll1.MaxHeight = halfHeight + c1Additional;
Scroll2.MaxHeight = halfHeight + c2Additional;
}
else
{
Scroll1.MaxHeight = double.PositiveInfinity;
Scroll2.MaxHeight = double.PositiveInfinity;
}
}
}
I only used the canvas to measure the size available inside the window, this could be done differently as well ...
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>
I have a xaml (window) control which contains a grid and inside that grid, two stackpanel. The second stackpanel is set to "collapsed" per visibility. When the form loads and the button on the form is clicked, the xaml window shows up centered by setting WindowStartupLocation="CenterScreen". But when the button on the xaml is clicked to set the second stackpanel's visibility to visible, it doesn't center no more. Can anyone help resolve this issue or tell me on how to fix this?
Update: After looking closely at this, I think it may be because the visibility is set to collapsed? I've tried instead of collapsed, hidden, and it centered it but with the column being shown empty as it's used by the stackpanel.
Here are the codes:
Form1.cs
public Form1()
{
InitializeComponent();
this.StartPosition = FormStartPosition.CenterScreen;
}
private void button_Click(object sender, EventArgs e)
{
MainWindow childWindow = new MainWindow();
childWindow.Show();
}
MainWindw.xaml
<Window x:Class="ChildProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:ChildProject"
Title="MainWindow"
Width="Auto"
Height="Auto"
SizeToContent="WidthAndHeight"
AllowsTransparency="False"
ResizeMode="NoResize"
WindowStyle="None"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<StackPanel x:Name="stkpnlMain"
Grid.Column="0"
Grid.Row="0"
Orientation="Vertical">
<Label Content="This is suppose to display message on right ..."
FontStyle="Italic"
FontWeight="Bold"/>
<Button Content="Click Me"
Width="75"
Margin="5" Click="Button_Click" />
</StackPanel>
<StackPanel x:Name="stkpnlDisplay"
Grid.Column="1"
Grid.Row="0"
Margin="5,0,0,0"
Orientation="Vertical"
Background="YellowGreen" Visibility="Collapsed" >
<Label Content="... First now shows ..."
BorderBrush="Black"
BorderThickness="1"
Background="Yellow" />
<Label Content="Hopefully this will work"
BorderBrush="Red"
BorderThickness="3"
Margin="0,5"
Background="White" />
</StackPanel>
</Grid>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
stkpnlDisplay.Visibility = Visibility.Visible;
}
In my project lots of views must have Ok,Cancel button to bottom of view. So i want create a base control. And add Ok, Cancel button to bottom of this control. Then i will inherite this control. In the inherited control i want to ad a textbox to near this buttons. How can i do this?
I believe there is a template for the base control.Is so in the inherited control's template edit the button panel and add textbox.
You can create Control which is inherited from ContentControl and define your buttons in ControlTemplate of it. Then you can just use this control as shown in sample.
ControlWithButtons.cs
[TemplatePart(Name="btnOk", Type= typeof(Button))]
public class ControlWithButtons : ContentControl
{
public ControlWithButtons()
{
this.DefaultStyleKey = typeof(ControlWithButtons);
}
Button _btnOk;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_btnOk = GetTemplateChild("btnOk") as Button;
if (_btnOk != null)
{
// do what you want with you button
_btnOk.Click += new RoutedEventHandler(_btnOk_Click);
}
}
void _btnOk_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Ok button clicked");
}
}
Generic.xaml (must be in (ProjectDir)/Themes/Generic.xaml)
(do not forget xmlns:local="clr-namespace:Test")
<Style TargetType="local:ControlWithButtons">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ControlWithButtons">
<Border Background="Yellow" CornerRadius="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Border Margin="10" Background="LightGray">
<ContentPresenter/>
</Border>
<Button Grid.Row="1" x:Name="btnOk" Content="OK" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="5"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Using your control:
<Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<local:ControlWithButtons Width="300" Height="250" HorizontalAlignment="Center" VerticalAlignment="Center">
<!-- TextBox is put into control -->
<TextBox Width="200" Height="Auto" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5" />
<!-- You can also specify ContentTemplate for ControlWithButtons -->
<!-- (see in MSDN "http://msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol.contenttemplate(v=vs.95).aspx") -->
</local:ControlWithButtons>
</Grid>
I found the solution. [ContentProperty("")] attribute solved my problem.
Like this:
Base Xaml
<Grid Name="layoutRoot" VerticalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="289*" />
<RowDefinition Height="51" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="1" Grid.Column="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Orientation="Horizontal">
<Button Name="btnOk" Content="Ok" Height="23" Width="75" HorizontalAlignment="Left" Margin="10,10,10,10" Command="{Binding Path=OnApply, Mode=OneWay}"/>
<Button Name="btnCancel" Content="Cancel" Height="23" Width="75" HorizontalAlignment="Left" Margin="10,10,10,10"/>
</StackPanel>
<Grid Name="rootContent" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Column="0" Grid.Row="0" />
</Grid>
</sdk:ChildWindow>
Base CodeBehind
[ContentProperty("RootContentControl")]//This attribute solved my problem.
public partial class BaseView : ChildWindow
{
public BaseView()
{
InitializeComponent();
}
public UIElementCollection RootContentControl
{
get { return rootContent.Children; }
}
}
Inherited Xaml
<Views:BaseView x:Class="MvvmLight1.Views.InheritedView"
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:Views="clr-namespace:MvvmLight1.Views"
xmlns:viewModels="clr-namespace:MvvmLight1.ViewModel"
mc:Ignorable="d" d:DesignHeight="244" d:DesignWidth="392"
DataContext="{Binding Source=viewModels:InheritedViewModel}">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
</Grid>
</Views:BaseView>
Inherited CodeBehind
public partial class InheritedView : BaseView
{
public InheritedView()
{
InitializeComponent();
}
}