trigger function in UserControl after Button Click in MainWindow (WPF) - c#

I have a UserControl inside of my MainWindow. I want to trigger function updateView() inside of my UserControl after clicking on my button in my MainWindow.
How can I achieve this?
Thanks in advance.
MainWindow.xaml
<local :UserControl></local>
<Button x:Name="btn_start" Click="btn_start_Click"></Button>
MainWindow.xaml.cs
private void btn_start_Click(object sender, RoutedEventArgs e) {
//trigger updateView in UserControl.xaml.cs
}
UserControl.xaml.cs
private void updateView() {
//start something in UserControl, this is irrelevant
}

One of the easiest way is to assign an instance using x:Name like this
<local:UserControl x:Name="yourusercontrolinstance"/>
And then in usercontrol the function's access specifier must be public, then you can invoke that method via the instance.
yourusercontrolinstance.updateView();

Related

Handling a custom control event from the parent window [duplicate]

This question already has answers here:
How can I create a click event on a custom user control?
(3 answers)
Closed 2 years ago.
This post was edited and submitted for review 3 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I have a custom control, lets call it uc_mycontrol, inside this control, I have a button lets name it btn_demo.
So in my mainwindow.xaml , i have an instance of the uc_mycontrol. I want to use the btn_demo click event handler, but I want to declare the event handler within the mainwindow's class, rather than declaring the event handler in uc_mycontrol's class. I know that the best way to handle the click event is by defining it inside uc_mycontrol but I specifically want to handle this event on the mainwindow
In summary, I have a custom control, with a button on it. I have instantiated the custom control on a window. I want to handle the button click event within the window, rather than from within the custom control.
You can define a custom event in your uc_mycontrol. Then, on bt_demo click event, very if the custom delegate has subscribers. If yes, fire the custom event.
public partial class uc_mycontrol : UserControl
{
public delegate void MyControlClickEvent(object sender, RoutedEventArgs e);
public event MyControlClickEvent OnControlClickEvent;
public uc_mycontrol()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.OnControlClickEvent?.Invoke(sender, e);// sender = the button
//this.OnControlClickEvent?.Invoke(this, e); // sender = this control
}
}
Add your custom control to MainWindow.xaml and subscribe to the custom event.
<Window x:Class="StackOverFlowWPF.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:StackOverFlowWPF"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:uc_mycontrol HorizontalAlignment="Left" Height="293" Margin="89,64,0,0" VerticalAlignment="Top" Width="547"
OnControlClickEvent="uc_mycontrol_OnControlClickEvent">
</local:uc_mycontrol>
</Grid>
In your MainWindow.xaml.cs, you will have:
private void uc_mycontrol_OnControlClickEvent(object sender, RoutedEventArgs e)
{
MessageBox.Show("Message");
}

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.

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

How to handle events from ResourceDictionary without using ResourceDictionary Code-Behind?

I would like help regarding how to handle events from controls in a ResourceDictionary (e.g. Styles.xaml) without using ResourceDictionary Code-Behind (e.g. Styles.xaml.cs), mainly because I want the Styles.xaml to just be there for styling.
My scenario is, I have a Custom Page which uses a ResourceDictionary for DataTemplate styles (I am using a TemplateSelector). However, the problem I am currently having is for handling events. For example:
I have this in my Styles.xaml:
.
.
<Button Click="Button_Click"/>
.
And I declare this in the CustomPage.xaml.cs :
private void Button_Click(object sender, RoutedEventArgs e)
{
// some code
}
However, it does not work. Is there any way to explicitly tell that I want to use that particular Event Handler for the button's click event? Additionally, is it possible to have different handlers for each page e.g.
CustomPage2.xaml.cs:
private void Button_Click(object sender, RoutedEventArgs e)
{
// some different code from CustomPage.xaml.cs
}
Thank you!
The answer is simple: do not handle events such a way. Use bindings instead (especially, if you're using data templates). E.g., for Button:
<Button Command="{Binding MyCommand}">
where MyCommand is a ICommand-implemented instance from your data context.
If you're not familiar with data bindings in WPF, start read from here.

UserControl calling methods and using variables outside it's class

I have a UserControl that looks like this:
<UserControl x:Class="Test3.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Button Name="mybutton" Content="Button Content"/>
</Grid>
</UserControl>
And a main window that uses it like so:
<Window Name="window_main" x:Class="Test3.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test3">
<StackPanel>
<Label Name="mylabel" Content="Old Content"/>
<local:UserControl1/>
</StackPanel>
</Window>
What I want to happen, is for mybutton's click event handler to set the content of mylabel to "New Content". However, it appears that this is impossible. Is there in fact a way to do this?
I have chosen to answer this myself since my solution ended up being a bit more complete. I don't fully understand the "right" way to do this, but this is how I did it:
Window1 window_reference = (Window1)(Window1.GetWindow((Button)sender));
After this, the children (such as other xaml controls) of the main window can be seen at compile-time.
Additionally, a more direct way of doing this is to have a public member of the UserControl like so:
namespace UIDD_Test
{
public partial class UserControl1 : UserControl
{
public Window1 window_reference;
public UserControl1()
{
InitializeComponent();
}
}
}
Then whenever appropriate, you can set that member to reference whatever window you want. In my case I have a Window1 class which is derived from Window, so I can set that member of the UserControl1 class like so:
myusercontrol.window_reference = window_main;
Where I've set up the xaml like so:
<local:UserControl1 x:Name="myusercontrol"/>
And window_main is the Name of the main window (it's a Window1 class).
There are several solutions:
The quick and dirty: on mybutton's click event handler, find the parent Window using VisualTreeHelper, then do a ((Label) window.FindName("mylabel")).Content = "New Content".
The clean WPF way: create a new class, add a property object LabelContent and a property ICommand ChangeContentCommand, that will change LabelContent on execution. Set this class as the DataContext of the window, bind the Content of mylabel to LabelContent and the Command property of mybutton to ChangeContentCommand (the user control will inherit the data context).
The simplest way to do what you describe is to take advantage of event routing and just add a handler in the Window XAML:
<StackPanel ButtonBase.Click="Button_Click">
<Label Name="mylabel" Content="Old Content"/>
<local:UserControl1/>
</StackPanel>
and the handler method:
private void Button_Click(object sender, RoutedEventArgs e)
{
mylabel.Content = "New Content";
}
I suspect you probably have some more complications to this in your real application so you may need to do more to verify that the click is coming from the correct button by checking some properties on it.

Categories