xaml window doesnt center - wpf

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;
}

Related

WPF WindowChrome unwanted black shadow - Caused by SizeToContent="WidthAndHeight"

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;
}

Grid splitter behavior (Expand top panel when bottom panel closes)

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);
}

Both MouseDown and KeyDown event is not fired even though Focusable is set to true

I'm trying to get my textblock to fire some events, and the resource here says that:
First of all you will need to set the Focusable Property of your
TextBlock to True, This will allow you to Tab to the Item but not
Click to select it, but if you handle the MouseDown Event you can
manually set Focus to your TextBlock.
That was what I did with the following (slightly modified)sample:
XAML code ( MainWindow.xaml)
<Window x:Class="databinding_tutorial.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Personal Details"
Height="180"
Width="250"
ResizeMode="NoResize">
<Grid Margin="5" Name="gridName">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock>First Name</TextBlock>
<TextBox Grid.Column="1" Margin="5 0 0 5"/>
<TextBlock Name="LastNameTB" Grid.Row="1" KeyDown="LastNameTB_KeyDown" Focusable="True" MouseDown="LastNameTB_MouseDown">Last Name</TextBlock>
<TextBox Grid.Column="1" Grid.Row="1" Margin="5 0 0 5"/>
<TextBlock Name="AgeTB" Grid.Row="2">Age</TextBlock>
<StackPanel Name="stackPan" Grid.Column="1" Grid.Row="2" Margin="5 0 0 5">
<Slider Minimum="16" Maximum="120" />
<TextBlock Name="stackPanTB" Text="16" HorizontalAlignment="Center"/>
</StackPanel>
<Button Grid.Column="1" Grid.Row="3" HorizontalAlignment="Right">New Window</Button>
</Grid>
</Window>
MainWindow.xaml.cs
/// <summary>
/// Interaction logic for MainWindow.xaml
/// http://www.blackwasp.co.uk/WPFDataContext.aspx
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var ageName = AgeTB.Text;
}
private void LastNameTB_KeyDown(object sender, KeyEventArgs e)
{
var ageName = AgeTB.Text;
LastNameTB.Background = Brushes.Blue;
}
private void LastNameTB_MouseDown(object sender, MouseButtonEventArgs e)
{
LastNameTB.Focus();
}
}
In my case here, neither the MouseDown nor the KeyDown event is fired... any reason?
You added events for textblocks not for textbox , Events will work for textblock
Remove and add events to TextBox
<TextBlock Name="LastNameTB" Grid.Row="1" >Last Name</TextBlock>
<TextBox Grid.Column="1" Grid.Row="1" Margin="5 0 0 5" KeyDown="LastNameTB_KeyDown" Focusable="True" MouseDown="LastNameTB_MouseDown"/>

How to use content of derived controls in silverlight

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();
}
}

Drag and drop between ListBox items and Grid cells in WPF?

There is a list box with some items in it. Also there is a grid with 3x3 matrix. The user will be dragging an item and dropping on one the cells of grid.
Most of the samples I found are about dragging-dropping from one listbox to another listbox. But I want to drop in one cell of grid. How can I achieve this?
Please advise. thanks
PJ
pls, check if an example below would work for you:
xaml:
<Grid>
<ListBox Height="100" HorizontalAlignment="Left" Margin="56,65,0,0"
Name="listBox1" VerticalAlignment="Top" Width="120"
PreviewMouseLeftButtonDown="listBox1_PreviewMouseLeftButtonDown">
<ListBoxItem Content="one" />
<ListBoxItem Content="two" />
<ListBoxItem Content="three" />
</ListBox>
<Grid Height="100" HorizontalAlignment="Left" Margin="238,65,0,0" Name="grid1"
VerticalAlignment="Top" Width="200" ShowGridLines="True" TextBlock.Drop="grid1_Drop">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" AllowDrop="True"></TextBlock>
<TextBlock Grid.Row="0" Grid.Column="1" AllowDrop="True"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0" AllowDrop="True"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1" AllowDrop="True"></TextBlock>
</Grid>
</Grid>
code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void listBox1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
object item = listBox1.SelectedItem;
if (item != null)
DragDrop.DoDragDrop(listBox1, item, DragDropEffects.Move);
}
private void grid1_Drop(object sender, RoutedEventArgs e)
{
TextBlock textBlock = e.Source as TextBlock;
Console.WriteLine("drop item into grid column:{0} row:{1}",
Grid.GetColumn(textBlock), Grid.GetRow(textBlock));
DataObject item = (((DragEventArgs)e).Data) as DataObject;
ListBoxItem listItem = item.GetData(typeof(ListBoxItem)) as ListBoxItem;
textBlock.Text = listItem.Content.ToString();
}
}
hope this helps, regards

Resources