Window.show not loading contents in wpf - c#

I am trying to bring up a window as a loading screen using the system.windows.window.show() method. The program is supposed continue running code and then close the window after it is done. The problem is that the window will not show the textblock I am trying to display. But when I do ShowDialog() it will
LoadingWindow lw = new LoadingWindow();
lw.Show();
//
//do stuff
//
lw.Close();
<Window x:Class="RevitAPITest3.LoadingWindow"
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:RevitAPITest3"
mc:Ignorable="d"
Title="Loading..." Height="450" Width="800" >
<Grid>
<TextBlock x:Name="text" FontSize="20" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Height="43" Width="291">testing</TextBlock>
</Grid>
</Window>

There's a fundamental difference between lw.Show() and lw.ShowDialog().
lw.Show() will immediately return to the next line of code without waiting for the window to close.
lw.ShowDialog() will wait for the window to close manually by the user, then return a value of true/false.
In your example code, your problem is that because lw.Show() returns immediately, it will then "do stuff" and then call lw.Close() which closes your window before you even see the window.
What you'll want to do is something like this. Notice: You never have to explicitly call lw.Close() because the window will automatically be closed as soon as it completes the lw.ShowDialog() line.
var result = lw.ShowDialog();
if (result.HasValue)
{
//
//do Stuff
//
}

Here is a complete working solution. Check to see where you are doing things differently and see if you can match this implementation.
MainWindow.xaml
<Window x:Class="LoadingWindowTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="768" Width="1024" WindowStartupLocation="CenterScreen">
<Grid>
<TextBlock Text="Main Window" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="32"/>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Threading.Tasks;
using System.Windows;
namespace LoadingWindowTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private LoadingWindow lw;
public MainWindow()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private async void OnLoaded(object sender, RoutedEventArgs e)
{
// Make the main window hidden until loading is done
this.Visibility = Visibility.Hidden;
// Show the Loading window
lw = new LoadingWindow();
lw.Show();
// Simulate a long running task
await Task.Delay(5000);
// Close the Loading window
lw.Close();
// Show the Main Window
this.Visibility = Visibility.Visible;
}
}
}
LoadingWindow.xaml (no xaml.cs shared because I didn't touch it)
<Window x:Class="LoadingWindowTest.LoadingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="LoadingWindow" Height="450" Width="800" WindowStartupLocation="CenterScreen">
<Grid>
<Grid>
<TextBlock x:Name="text" FontSize="20" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Height="43" Width="291">testing</TextBlock>
</Grid>
</Grid>
</Window>
Build and Run, then this is the Expected Output:
You should see the LoadingWindow on the center of the screen, then after 5 seconds, it closes and the MainWindow shows.

Related

How to close a hidden main window in WPF?

I have two windows in a single application.
The first window has one button. When I click the button, the second window opens. (The first window needs to close or hide). Then I need to close my second window and need to stop the debugging. How to do it?
<Window x:Class="WpfApp5.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:WpfApp5"
xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
xmlns:Control="clr-namespace:Syncfusion.Windows.Tools.Controls;assembly=Syncfusion.Tools.Wpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Content="Create" Height="50" Width="100" Click="btncreate"></Button>
</Grid>
MainWindow code-behind:
public partial class MainWindow : Window
{
public static TextBox textBox;
public MainWindow()
{
InitializeComponent();
}
private void btncreate(object sender, RoutedEventArgs e)
{
SecondWindow secondWindow = new SecondWindow();
secondWindow.Owner = this;
this.Hide();
secondWindow.ShowDialog();
}
}
Second window:
<Window x:Class="WpfApp5.SecondWindow"
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:WpfApp5"
mc:Ignorable="d"
Title="SecondWindow" Height="450" Width="800">
<Grid>
<StackPanel>
<TextBlock Text="New Project Loaded" HorizontalAlignment="Center" Margin="50"></TextBlock>
</StackPanel>
</Grid>
Your problem seems to be that you're running code which is showing a window, maybe modally.
At the same time, you're trying to shut the app down.
You've not shown this code but if your btnCreate handler has shutdown in it just before
secondWindow.ShowDialog();
You'd be trying to shut the app down effectively at the same time as showing that window as a dialog.
What you want is your code to shut the app down but not whilst the UI is busy doing something else like show a window.
You could do that by moving your shutdown so it's in say the contentrendered event handler of that window you're showing.
Another option is to schedule the shutdown using dispatcher.
Application.Current.Dispatcher.InvokeAsync(new Action(() =>
{
Application.Current.Shutdown();
}), DispatcherPriority.ContextIdle);
If you still have errors you could consider instead using.
Environment.Exit(0);
This is a rather brute force approach compared to shutdown but if you're only doing this whilst debugging that probably won't matter.
In any case, you should ensure you don't have code which shows another window or something from the window.closing events of any of your windows. Since closing the app will necessarily involve closing windows.

How to create child window by the context menu of page in wpf?

I have a context menu what is triggered by each list item of listbox.
And, I want to create child window when I select a context menu as below:
xaml
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Width="150" Orientation="Vertical" Margin="15, 5, 15, 5">
<StackPanel.ContextMenu>
<ContextMenu FontSize="16">
<MenuItem Header="{x:Static localRes:Resources.ID_STRING_SETTING}" Margin="5" Command="Setting_Click"/>
</ContextMenu>
It is already a sub page of main window.
So, I can't find a way how to set MainWindow instance as the owner of new window.
Behind Code
private void Setting_Click(object sender, RoutedEventArgs e)
{
SettingWindow SettingWindow = new SettingWindow();
SettingWindow.Owner = /* I do not know how to do */
SettingWindow.Show();
}
If your click command handler is in the code behind for your main window, then you need to set
deviceSettingWindow.Owner = this;
https://learn.microsoft.com/en-us/dotnet/api/system.windows.window.owner?view=netframework-4.8
Here's a small example. It includes a button with a handler whose code is in the code behind -
<Window x:Class="MainWindow.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:ChildWindow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="114,137,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
</Window>
CodeBehind:
using System.Windows;
namespace MainWindow
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var childWindow = new ChildWindow.Window1();
childWindow.Owner = this;
childWindow.Show();
}
}
}
Child Window - just an empty window
<Window x:Class="ChildWindow.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:ChildWindow"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<Grid>
</Grid>
</Window>
Child Window Code Behind
using System.Windows;
namespace ChildWindow
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
In my example, Since you are in the code behind for the MainWindow, this is a reference to the MainWindow, and setting 'childWindow.Owner = this' is setting the childWindow's owner to the MainWindow which is what I believe you want.
One thing that is a little confusing to me is that you are using a Command and a reference to an event handler in the code behind. I'm pretty sure that's not going to work. Commands need to Bind to an ICommand reference - you'll have to implement your own ICommand class, or use one from MVVM Light or another WPF MVVM Framework. Once you've got that you can pass a reference from the parent window through the Command as a CommandParameter. For an example of how to do this, see passing the current Window as a CommandParameter
If you are using an event handler on a control, then that can bind to the event handler implementation in the code behind like in my example. You need to choose one or the other.
If you're able to provide more details on how you're setup, it would make it easier for me to provide input on which way you need to go.

How to Load a WPF window in the MainWindow as a TabControl item?

The structure of my MainWindow.xaml is as bellow
<Window>
<Grid>
<TabControl Name="MainTabCntrl">
<TabItem1>
<TabItem2>
<TabItem3>
.
.
.
<TabItemN>
</TabControl>
</Grid>
</Window>
The problem is that my MainWindow.xaml is currently ~4000 lines of code,which is not efficient(do you agree?)
the solution I'm trying to implement is to create N windows (representing my TabItems) separately and each time user click on Tab items I load the related windows in that TabItem as shown bellow
private void inventory_start()//this function is called in my MainWinodw.xaml.cs
{
inv = new Inventory(db, logViewer);//this is a window
TabItem tbItem = new TabItem();
Frame frame = new Frame();
frame.Content = inv;
tbItem.Name = "invTab";
tbItem.Content = frame;
tbItem.IsSelected = true;
MainTabCntrl.Items.Add(tbItem);
inv.swithInventoryTabs("inv_info");
}
I have an error now , "'Management_V0.Inventory' root element is not valid for navigation."
A window cannot be a child of another element. Period.
But you could just move the contents of the Inventory window to a UserControl (by for example simply copy and paste the XAML and the code from one file to another) and use this one as the Content of the Inventory window and the Frame:
<Window x:Class="WpfApplication1.Inventory"
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:WpfApplication1"
mc:Ignorable="d"
Title="Inventory" Height="300" Width="300">
<local:UserControl1 />
</Window>
Frame frame = new Frame();
frame.Content = new UserControl1();
best way to use tabControl is with User control: Example below:
XAML
<TabControl >
<TabItem x:Name="tab1" Header="UserControl"></TabItem>
<TabItem x:Name="tab2" Header="noControl"></TabItem>
</TabControl>
and in code behind class:
tab1.Content = new UserControl1();
and than Add new user control of name UserControl1:
<UserControl x:Class="WpfApplication1.UserControl1"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Viewbox>
<TextBlock Text="User Control"/>
</Viewbox>
</Grid>
</UserControl>

WPF Thumb drag and move with WindowState.Maximized

I have custom window with WindowState=WindowState.Maximized with border and thumb inside in the border, it seems that when the WindowState=WindowState.Maximized I cannot drag and move the custom window to different screen.
Xaml:
<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"
WindowStyle="None">
<Border Name="headerBorder"
Width="Auto"
Height="50"
VerticalAlignment="Top"
CornerRadius="5,5,0,0"
DockPanel.Dock="Top"
Background="Red"
BorderThickness="1,1,1,1"
BorderBrush="Yellow">
<Grid x:Name="PART_Title">
<Thumb x:Name="headerThumb"
Opacity="0"
Background="{x:Null}"
Foreground="{x:Null}"
DragDelta="headerThumb_DragDelta"/>
</Grid>
</Border>
</Window>
C#:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
WindowState = System.Windows.WindowState.Maximized;
}
private void headerThumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
Left = Left + e.HorizontalChange;
Top = Top + e.VerticalChange;
}
}
I've also overridden MouseLeftButtonDown method and using DragMove() inside but without success. I've also tried to subscribe to thumb's MouseLeftButtonDown and write there DragMove() but without success.
By default, maximized windows cannot be moved, thus Left and Top have no effect. One option would be to register to the Thumb.DragStarted event and check if the window is maximized. If yes, you can set WindowState.Normal and successively update the Left and Top properties.
In code, this would look somewhat like this:
private void Thumb_OnDragStarted(object sender, DragStartedEventArgs e)
{
// If the window is not maximized, do nothing
if (WindowState != WindowState.Maximized)
return;
// Set window state to normal
WindowState = WindowState.Normal;
// Here you have to determine the initial Left and Top values
// for the window that has WindowState normal
// I would use something like the native 'GetCursorPos' (in user32.dll)
// function to get the absolute mouse point on all screens
var point = new Win32Point();
GetCursorPos(ref point);
Left = point - certainXValue;
Top = point - certainYValue;
}
You can learn more about GetCursorPos here.
However, I would strongly advise you to use the WindowChrome class that comes with .NET 4.5 and that was also suggested by Max in the comments. You just have to use the following code and you have the functionality you're asking for:
<Window x:Class="ThumbMaximizedWindow.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"
WindowStyle="None"
WindowState="Maximized">
<WindowChrome.WindowChrome>
<WindowChrome />
</WindowChrome.WindowChrome>
</Window>

Bringing a user control to the front in Expression Blend, C#, WPF

I have a window with a Grid on.
On this I have some buttons, one of which when clicked will create a new 'PostIt' which is a user control I have created.
What I want to do is click on a 'PostIt' and have that control on top of all the others.
I have tried...
Grid.SetZIndex(sender, value);
Which seems to be the correct code, no errors, just not movement of the control :(
The problem may lie in the fact that the code for the click is in the user control and not the mainwindow cs file. Does this matter?
The 'PostIt' is simply a border with a text box in it.
Are you calling Grid.SetZIndex(sender, value) in a handler of the PostIt mouse click, or a handler for a control inside the PostIt? What is the value that you are setting?
Here is an example that works:
<UserControl x:Class="WpfApplication1.UserControl1"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" MouseUp="UserControl_MouseUp">
<Grid>
</Grid>
</UserControl>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void UserControl_MouseUp(object sender, MouseButtonEventArgs e)
{
Panel.SetZIndex(this, Panel.GetZIndex(this) + 2);
}
}
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:UserControl1 Background="Green" Margin="40,40,100,100" Panel.ZIndex="0" />
<local:UserControl1 Background="Red" Margin="140,140,10,10" Panel.ZIndex="1" />
</Grid>
</Window>
Jogy
This may not be the best solution, but it's the one that worked for me; I was re-ordering two grids:
GridOnBottom.SetValue(Grid.ZIndexProperty, (int)GridOnTop.GetValue(Grid.ZIndexProperty) + 1);
...with GridOnBottom and GridOnTop renamed to the instances of the objects you're re-ordering. Granted, it's not the best solution, but it works.

Categories