WindowLoaded event in WPF - c#

I have added WindowLoaded event as a routed event handler in constructor but not sure if this is a right way of declaring/suing loading of a window.
this.AddHandler(Window.LoadedEvent, new RoutedEventHandler(WindowLoaded));
Currently seems working since as soon as I run the App I get a empty window with borders only without its contents.
Question is that how can I use WindowLoaded() event in WPF? I was expecting to select it from top dropdown box in VS2010 but I guess have to enter it manually. Is that right?
Cheers,
Amit

You can set the Loaded event in either the GUI:
Or in the codebehind of the control:
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded( object sender, RoutedEventArgs e )
{
}

You can follow Mark's advice, or alternatively, you can add the loaded event in your MainWindow.xaml (Visual Studio will generate the handler for you if you press ctrl+space in the Loaded attribute):
<Window x:Class="StackOverflowWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="MainWindow_Loaded">
<!-- your code -->
</Window>

Related

C#/AvaloniaUI - Click a button and change Text

I am very new to AvaloniaUI.
I am really struggling to change a text when I click a button.
Here is my code:
<Window xmlns="https://github.com/avaloniaui"
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" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ReadyForWar_Launcher.MainWindow"
Title="ReadyForWar_Launcher">
<StackPanel>
<TextBlock Name="TestBlock">Show my text here!</TextBlock>
<Button Command="{Binding RunTheThing}" CommandParameter="Hello World">Change the Text!</Button>
</StackPanel>
</Window>
Here is my MainWindow.xaml.cs:
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace ReadyForWar_Launcher
{
public class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public void RunTheThing()
{
}
}
}
Inside RunTheThing I don't know how can I select the TextBlock with Name="TestBlock" and change the text to "Hello World".
Can you please help me out on this ?
There are two approaches, the recommended one and straightforward one.
Recommended: Use MVVM pattern. Create a view model with ButtonTextProperty and RunTheThing command, make the command to change the property, assign that model to the DataContext and bind your button text and command to view model properties. The MVVM approach is basically the same as in WPF, so you can use documentation and tutorials from there (that applies to most of the Avalonia, BTW). For example, here is a good one (not advertising, 4th link from google).
Straightforward (aka winforms-way): add x:Name="MyButton" to your button and use this.FindControl<Button>("MyButton") after calling AvaloniaXamlLoader.Load(this);. This will give you a Button reference that you can manipulate from code. Instead of using commands, you can just subscribe to the click handler directly from codebehind, add public void MyButton_OnClick(object sender, RoutedEventArgs args){} to your MainWindow class and add replace Command and CommandParameter with Click="MyButton_OnClick". That way button click will trigger your event handler.
Note, that the second approach doesn't scale well with the application size and suffers from code complexity when handling lists.

WPF call Window_Closing event from code behind

Recently I have been experimenting with WPF. I was building a little program, but then I stumbled across a little problem. I tried to call the Window_Closing method from the code behind, it told me that I needed to give it cerntain parameters, but I don't have those parameters in the method I am trying to call it from.
This is my code:
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// My Window Closing code
}
private void Application_Exit(object sender, RoutedEventArgs e)
{
// Here is where I am trying to call it, giving a empty parameter with it.
// But it doesn't seem to work.
Window_Closing(null, EventArgs.Empty)
}
What I want
If a cenrtain button is called, I want the Window_Closing event to be called.
Anyone who knows the solution?
In your Designer, click on the Button and open its property window. There you select the "Events" - the "lightning" and choose the Click event to execute your Window_Closing method. There is a drop down in which you should be able to select it. If not, enter your method name there and press "Enter" to let VS generate the code-behind method.
Add "Window_Closing" & "Close_Click" in the XAML file (MainWindow.xaml) as follows.
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" Closing="Window_Closing">
<Grid>
<Button x:Name="Close" Content="Close" Click="Close_Click" Width="100" Height="30"/>
</Grid>
Then in the code behind file (MainWindow.xaml.cs) add the following code. Here the window close command is called from the button click event handler which in turn closes the window, and then the 'Window_Closing' event handler will be automatically called.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
}
private void Close_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
Just close the window. Then the event will be called automatically, thats what it is there for to begin with.
And as it seems, you try calling it from your Application_Exit, which closes all the windows ... so .... What is your problem?
Just put a breakpoint in the Window_Closing and see, that is executed automatically. If not, maybe you should add the eventhander to all the windows Window_Closing events.

Two Loaded events with no intervening Unloaded in in second tab, is it a bug?

This is my MainWindow code, which contains a TabControl:
<Window x:Class="TabControlNS.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:TabControlNS"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TabControl Visibility="Visible">
<TabItem Header="Item2">
</TabItem>
<TabItem Header="Item1">
<ContentControl Loaded="ContentControl_Loaded">
<local:View/>
</ContentControl>
</TabItem>
<TabItem Header="Item3"/>
<TabItem Header="Item4"/>
</TabControl>
</Grid>
</Window>
<UserControl x:Class="TabControlNS.View"
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:local="clr-namespace:TabControlNS"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="grid">
</Grid>
</UserControl>
And here's the code behind:
public partial class View : UserControl
{
public System.Windows.Forms.Integration.WindowsFormsHost host;
public View()
{
InitializeComponent();
IsKeyboardFocusWithinChanged += View_IsKeyboardFocusWithinChanged;
host = new System.Windows.Forms.Integration.WindowsFormsHost();
var mtbDate = new System.Windows.Forms.MaskedTextBox("00/00/0000");
grid.Children.Add(host);
this.Loaded += View_Loaded;
this.Unloaded += View_Unloaded;
}
private double LoadMinusUnloadCount = 0;
private void View_Loaded(object sender, RoutedEventArgs e)
{
LoadMinusUnloadCount++;
}
private void View_Unloaded(object sender, RoutedEventArgs e)
{
LoadMinusUnloadCount--;
}
private void View_IsKeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine($"View.IsKeyboardFocusedWithin = {IsKeyboardFocusWithin}");
}
}
Since the local:View control is embedded inside "Item1", then View_Loaded will be called twice ( once when the Window is starting up, another when the "Item1" is coming to view). No Unloaded event has been called in between.
According to Same Bent of Microsoft, this is clearly a bug
I encourage you to report bugs about things that are clearly wrong,
such as
Unloaded events with no matching Loaded
Two Loaded events with no intervening Unloaded
Element clearly visible and active but no Loaded
Or is it? Can Microsoft make such an elementary bug with such a control? How to explain this?
I'm not sure if it's a bug, but there are really several controls in WPF behaviors like this.
The controls that will raise Loaded twice without Unloaded are:
TabControl
Popup
When the controls are added to the visual tree, the Loaded event will be raised to all of its children. And when the child shows or opens, the Loaded event will raise again. When the child closes, the Unloaded event will raise once. And when the TabControl or Popup was removed from the visual tree, the Unloaded event will be raised again.
When a tab control is added to a visual tree:
TabControl Loaded -> TabItem0 Loaded -> TabItem1 Loaded -> …
When the tab control changed tab:
Old Active Tab Unloaded -> New Active Tab Loaded
This means that all TabItems will be Loaded twice and Unloaded twice.
The Popup has a similar behavior.
When a popup is added to a visual tree:
Popup Loaded -> Child Loaded
When the popup is opened:
Child Loaded
When the popup is closed:
Child Unloaded
When the popup is Removed from a visual tree:
Popup Unloaded
But if the popup is opened and is removed from a visual tree:
Popup Unload -> Child Unloaded (This may be not very expected.)
Actually, I believe that WPF has many bugs. My friends and I post them on GitHub:
The undefined behaviors of WPF Grid (the so-called bugs) - walterlv
dotnet-campus/wpf-issues: This repository provides small demo programs and code snippets to reproduce several wpf-related bugs.
dotnet-campus/TouchIssueOnWindows10.0.17134: On Windows 10 (1803), all applications lost touch or stylus if a WPF transparent window covers on them

KeyDown event not raising from a grid

Here I have sample window with a grid. I need to capture event when key is pressed. But it is not raising when I click grid area and then press key. It will work only if Textbox is focused. I know it will work if I capture it from Window. But I have other application with few usercontrols and I need to capture it from distinct ones. I tried to set Focusable.false for Window and true for Grid but it not helps.
Any solutions?
<Window x:Class="Beta.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" Closed="Window_Closed_1" Focusable="False">
<Grid KeyDown="Grid_KeyDown_1" Focusable="True">
<TextBox x:Name="tbCount" HorizontalAlignment="Left" Height="35" Margin="310,49,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="83"/>
</Grid>
Right this is weird. This is clearly a focus problem, still I can not understand why the grid do not take Focus, even when we click on it.
Though there is a workaround: create an handler for the loaded event of the grid:
<Grid x:Name="theGrid" KeyDown="Grid_KeyDown_1" Focusable="True" Loaded="TheGrid_OnLoaded">
And then force focus in your code behind:
private void TheGrid_OnLoaded(object sender, RoutedEventArgs e)
{
theGrid.Focus();
}
Your keydown event will work after that.
Hope it helps.
I had the same issue with a Universal Windows Platform (UWP) app. I attached the event to a grid in XAML but it would only work when the focus was on the TextBox. I found the answer (not just a workaround) on MSDN: https://social.msdn.microsoft.com/Forums/en-US/56272bc6-6085-426a-8939-f48d71ab12ca/page-keydown-event-not-firing?forum=winappswithcsharp
In summary, according to that post, the event won't fire because when focus to the TextBox is lost, it's passed higher up so the Grid won't get it. Window.Current.CoreWindow.KeyDown should be used instead. I've added my event handlers to the page loaded event like this:
private void Page_Loaded(object sender, RoutedEventArgs e)
{
Window.Current.CoreWindow.KeyDown += coreWindow_KeyDown;
Window.Current.CoreWindow.KeyUp += CoreWindow_KeyUp;
}
This works as expected for me.
I tried using the Focus Method too, to no avail, until I set the Focusable property to true ( It was default to False. )
I had the same problem, I've used PreviewKeyDownevent and it worked for me.

Cannot drag text into a WPF window

I'm trying to set up a WPF window so that it can accept different types of data via Drag and Drop. If I make a new project and set the window to the following:
<Window x:Class="DropShare.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" AllowDrop="True" DragEnter="Window_DragEnter">
<Grid>
</Grid>
</Window>
And set the code-behind to:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Window_DragEnter(object sender, DragEventArgs e)
{
}
}
I only ever get DragEnter firing for files. It never fires for anything else - text, images, etc.
Is there something I'm missing? All the tutorials I've read have seemed to suggest this is all that's needed as the DragEnter event handler let's me state what I accept.
So your code works fine for me. But try this...
In your Window:
<Label Background="Purple" HorizontalAlignment="Center" VerticalAlignment="Center" Content="Drag from here!" MouseDown="Label_MouseDown"/>
and in your code behind:
private void Label_MouseDown(object sender, MouseButtonEventArgs e)
{
DragDrop.DoDragDrop(this, "This is just a test", DragDropEffects.All);
}
Then drag from the label into the window and see if your event fires.
If this works, it may have something to do with the permissions level between Visual Studio and your outside environment (possibly).
See:
https://superuser.com/questions/59051/drag-and-drop-file-into-application-under-run-as-administrator
In WPF drag and drop feature always has to deal with DragDrop Class, Please check here how to do drag and drop across applications

Categories