dual monitor parent child window issue - c#

I have two monitors. When my application runs, the parent is displayed on the first monitor. When I move the parent window to the second monitor and click a button (diaplay a xaml window for loading), this child window stays on the first monitor. Is there a way to make the child window stay with the parent window no matter where the parent window is located?
please note: parent is winform ... child is xaml.
loading xaml (child)
<Window x:Class="Test.Loading"
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"
WindowStyle="None"
AllowsTransparency="True"
WindowState="Maximized"
Background="Gray">
<Grid>
<Border>
<TextBlock Text="Loading ..." />
</Border>
</Grid>
</Window>
Parent
private void btnShowLoading_Click(object sender, EventArgs e)
{
Loading load = new Loading();
double top = this.Top;
double left = this.Left;
load.Top = top;
load.Left = left;
load.Show();
}

Try this:
childWindow.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
UPDATE 1:
Get your parent window's location and set it to child window.
If you think your parent window's state changes, you may use this to get actual Top and Left:
var leftField = typeof(Window).GetField("_actualLeft", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var topField = typeof(Window).GetField("_actualTop", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
double left = (double)leftField.GetValue(parentWindow);
double top = (double)topField.GetValue(parentWindow);
source: Window ActualTop, ActualLeft
UPDATE 2:
First of all you had to tell that the parentWindow is WinForms.
In this case you can get parentWindow's Top and Left like this:
double top = this.Top;
double left = this.Left;
Then pass the top and left of the parentWindow to the childWindow. When childWindow loaded it should set top and left.

In WPF you need to manually set the owner window - it is not done automatically. From Window.Show:
A window that is opened by calling Show does not automatically have a
relationship with the window that opened it; specifically, the opened
window does not know which window opened it. This relationship can be
established using the Owner property and managed using the
OwnedWindows property.
Since your Loading window has no owner, it will be centered on your primary monitor. Use the code below:
private void btnShowLoading_Click(object sender, EventArgs e)
{
Loading load = new Loading();
load.Owner = this;
load.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
load.Show();
}

Related

How to recenter UserControl(s) in Window

We have BaseDialogView with next xaml code:
<Window x:Class="Test.BaseDialogView"
Height="475"
WindowStartupLocation="CenterOwner"
SizeToContent="Height"
ResizeMode="CanResize"
SizeChanged="Window_SizeChanged">
<ContentControl Content="{Binding ContentPage}" />
</Window>
BaseDialogViewModel class:
public class BaseDialogViewModel : AbstractNotifyPropertyChangedItem
{
private UserControl contentPage;
public UserControl ContentPage
{
get { return this.contentPage; }
set
{
if (this.contentPage != value)
{
this.contentPage = value;
this.RaisePropertyChanged(() => this.ContentPage);
}
}
}
}
The usage is very simple:
BaseDialog dialog = new BaseDialog();
BaseDialogViewModel dialogVm = new BaseDialogViewModel();
dialog.Owner = Application.Current.MainWindow;
dialog.DataContext = dialogVm ;
dialogVm.ContentPage = new ActivationView();
dialogVm.ContentPage.DataContext = new ActivationViewModel();
So basically once you have an instance of BaseDialog, you just set ContentControl (by setting dialog.ContentPage and dialog.ContentPage.DataContext).
ActivationView is very simple. For example:
<UserControl x:Class="Test.ActivationView" d:DesignHeight="400" d:DesignWidth="700" MaxWidth="700">
<Grid> .... what ever you need
</UserControl>
The problem is that different UserControls windows are set, which have different width and height. When the first UserControl is shown it's place in the center of the MainWindow, which is ok. Then each new userControl is shown, but it's not centered. How do I center the BaseDialog window for each usercontrol?
I tried this (BaseDialogView):
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
Window w = sender as Window;
this.Top = (Application.Current.MainWindow.Height - w.ActualHeight) / 2;
}
but does not work ok (Some usercontrols are still not pixel centered). I also tried adding this to BaseDialogView Xaml
<Window .... VerticalAlignment="Center">
but it seems to be working only for initial instance.
First of you should really consider propperly implementing the MVVM pattern.
It will make your live easier, also instead of centering the element manually in the size change event you should set its owner and WindowStartupLocation by using
Window win = new Window();
win.Content = new MyUserControl();
win.Owner = this;
win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
Instead of having one window where you keep changing the content i would consider having different windows..but that may vary on your specific case

How do I position a window in WPF in an exact location?

I'm trying to display a window that aligns with an existing component. In this example I want to align it to a button. When i click the button I would like the window to position itself so that it's bottom is just above the button, and it's width is the same as the button. The left of the window should be the same as the left of the button.
To achieve this I use the following xaml:
<Window x:Class="WindowPositioningTest.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:WindowPositioningTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Name="MyButton" Content="Click me to see window!" Width="300" Height="50" Click="Button_Click"/>
</Grid>
The onclick function looks like this:
private void Button_Click(object sender, RoutedEventArgs e)
{
var window = new Window();
var myButtonLocation = MyButton.PointToScreen(new Point(0, 0));
window.Width = MyButton.ActualWidth;
window.Height = 300;
window.Left = myButtonLocation.X;
window.Top = myButtonLocation.Y - window.Height;
window.Show();
}
When I click the button a window is displayed like in the picture below.
My question is: why is the window not as wide as the button and why is it not in the right position? It's almost as if there's an invisible frame around the window.
Try this:
private void Button_Click(object sender, RoutedEventArgs e)
{
var window = new Window();
var myButtonLocation = MyButton.PointToScreen(new Point(0, 0));
window.Width = MyButton.ActualWidth + 16;
window.Height = 300;
window.Left = myButtonLocation.X - 8;
window.Top = myButtonLocation.Y - window.Height;
window.Show();
}
It happens beacuse of window border. As you know, window is a composite element. I think when you set Width, you set a width of the working space, not the width of the whole window.

XAML:Specified element is already the logical child of another element. Disconnect it first

I am building a Custom Modal Box in wpf Something like this
I want users to Add Modal Children Control element from XAML using some Custom Modal Element.
Since we cannot create a Child Window inside Main Window.
So I am doing it indirectly using xaml and c#.
Here is my sample code Implementing Modal
MainWindow.xaml
<local:ModalWindow>
<Border Background="Red" Width="400" Height="400">
<Button Width="110"></Button>
</Border>
</local:ModalWindow>
MainWindow.xaml.cs
class ModalWindow : StackPanel
{
public ModalWindow()
{
StackPanel myGrid = this;
this.Height = 400;
this.Width = 400;
Window myWindow = new MyWindow(this);
}
class MyWindow : Window
{
public MyWindow(object x) : base()
{
this.WindowState = WindowState.Maximized;
this.AllowsTransparency = true;
this.WindowStyle = WindowStyle.None;
this.Opacity = 0.7;
this.Background = Brushes.Black;
this.AddChild(x);
this.ShowDialog();
}
}
On loading it displays with an RunTimeError
Error: "Specified element is already the logical child of another element. Disconnect it first"
Is there any way to disconnecting this node from MainWindow first and then add this Exact node to my New Window as its child.
Please Help!

WPF New Window with content

I want create a new Window beside an existing main Windwoe with a scrollable Textbox.
I'm pressing in my main Window on a button "Open New Window" and then it should open a new Window with a scrollable Textbox.
inside form2
In WPF you can drag drop elements in the main Window but cant do that for a new window.
So I thought it is only possible when you create a new window in the MainWindow.xaml.cs
I was able to create a new Window trough:
private void btnConnect_Click(object sender, RoutedEventArgs
{
Form form2 = new Form();
//Do intergreate TextBox with scrollbar in form2
form2.Show();
}
and now I want a Textbox
But how can I do that in C# or WPF?
Thx
well... you can create a new Window and load into this Windows.Content a UserControl wich you createt in a new XAML.
Example:
NewXamlUserControl ui = new NewXamlUserControl();
MainWindow newWindow = new MainWindow();
newWindow.Content = ui;
newWindow.Show();
the Xaml is could be like this
<UserControl x:Class="Projekt"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="newXamlUserControl"
Height="300" Width="300">
<Grid>
<TextBox Text = ..../>
</Grid>
</UserControl>
Create a new WPF window in your project:
Project -> Add New Item -> Window (WPF)
Name the window appropriately (here I use ConnectWindow.xaml)
Add a TextBox to the XAML
<Window
x:Class="WpfApplication1.ConnectWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Connect"
Height="300"
Width="300"
ShowInTaskbar="False">
<TextBox
AcceptsReturn="True"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"/>
</Window>
You can customize both Window and TextBox as you like.
There are several ways to display the window.
Displaying a modal window (this refers to the main window):
var window = new ConnectWindow { Owner = this };
window.ShowDialog();
// Execution only continues here after the window is closed.
Displaying a modeless child window:
var window = new ConnectWindow { Owner = this };
window.Show();
Displaying another top-level window:
var window = new ConnectWindow();
window.Show();

Create a maximised window that in non resizable?

I have 2 windows now that i want to open maximized but should be non realizable?how would i do this?
To maximize the window use:
this.WindowState = System.Windows.WindowState.Maximized;
This will allow the window only to be minimized:
this.ResizeMode = System.Windows.ResizeMode.CanMinimize;
You can change it to the following if you want to disable minimizing as well:
this.ResizeMode = System.Windows.ResizeMode.NoResize;
Place the above in your form's constructor, it should look something like this:
public MainWindow()
{
InitializeComponent();
this.WindowState = System.Windows.WindowState.Maximized;
this.ResizeMode = System.Windows.ResizeMode.CanMinimize;
}
Or simply add the following properties to your window in XAML to make it look like this:
Title="MainWindow" ResizeMode="NoResize" WindowState="Maximized">
This can be done in WPF by following way:
window.WindowState = WindowState.Maximized;
In XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowState="Maximized">
...
</Window>

Categories