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");
}
Related
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.
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
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>
I have this simple UserControl:
<UserControl x:Class="WPFTreeViewEditing.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>
<TextBlock Text="Hello, world!" KeyDown="TextBlock_KeyDown" />
</Grid>
</UserControl>
I want to handle TextBlock.KeyDown event. So, I've added an event handler to the code-behind:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void TextBlock_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("Key up!");
}
}
but it doesn't fire. What's wrong?
UPDATE.
PreviewKeyDown doesn't fire too.
This UserControl is used in HierarchicalDataTemplate then:
<Window x:Class="WPFTreeViewEditing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFTreeViewEditing"
Title="MainWindow" Height="265" Width="419">
<Grid>
<TreeView ItemsSource="{Binding}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:ViewModel}" ItemsSource="{Binding Items}">
<local:UserControl1 />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
</Window>
From the documentation for UIElement.KeyDown:
Occurs when a key is pressed while focus is on this element.
You're using TextBlock which doesn't have the focus, so your KeyDown event will be handled by another control.
You can switch to TextBox and appy some styles so it'll look and behave like TextBlock, but you'll be able to get the focus and handle the event.
You should use PreviewKeyDown event instead of KeyDown event.
Ok, even though this question was posted a long time ago I had the same problem and found a way to get KeyDown events working, though it might not be what you're looking for I'll post the code to help future people with the same problem.
First thing first a KeyDown event handler in an Xaml Object will only fire off if that object has focus. Therefore you need a CoreWindow event handler, it's kind off the same thing but it will always run no matter what object or thing has focus. The following will be the code.
//CLASS.xaml.h
ref class CLASS{
private:
Platform::Agile<Windows::UI::Core::CoreWindow> window;
public:
void KeyPressed(Windows::UI::Core::CoreWindow^ Window, Windows::UI::Core::KeyEventArgs^ Args);
//CLASS.xaml.cpp
CLASS::CLASS(){
InitializeComponent();
window = Window::Current->CoreWindow;
window->KeyDown += ref new TypedEventHandler
<Windows::UI::Core::CoreWindow^, Windows::UI::Core::KeyEventArgs^>(this, &CLASS::KeyPressed);
};
void CLASS::KeyPressed(Windows::UI::Core::CoreWindow^ Window, Windows::UI::Core::KeyEventArgs^ Args){
SimpleTextBox->Text = Args->VirtualKey.ToString();
};
Basically you want a value to hold your window and use that to create a new TypedEventHandler. For safety you'll generally want to do this in your class' constructor a function that's only called once the moment the class starts (I still prefer the constructor though).
You can use this method to create an event handler for any event. Just change the "KeyDown" for another attribute like KeyUp, PointerMoved, PointerPressed and change the "&CLASS::KeyPressed" to the name of the function you want to be fired the moment you get an event of a corresponding type.
I have recently started to move my user controls in DLLs. These controls usually look something like this:
<UserControl x:Class="DialogBase.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"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Button Content="OK" Click="OkButton_Click"/>
</Grid>
</UserControl>
I want to able to use every button in the control like in a standard control. For example when somebody uses the control above, he should be able to handle the click event in an own method like this:
<lib:UserControl1
OkButtonClick="MyCostomClickMethod"
/>
I usualy achieve this like this: (code-behind file of user control)
public static RoutedEvent OkButtonClickEvent = EventManager.RegisterRoutedEvent("OkButtonClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(UserControl1));
public event RoutedEventHandler OkButtonClick
{
add
{
AddHandler(OkButtonClickEvent, value);
}
remove
{
RemoveHandler(OkButtonClickEvent, value);
}
}
private void OkButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(OkButtonClickEvent));
}
This works fine but very slow. The delay between a click and the resulting action can be up to a second. Can somebody tell me if there is a faster or in any way better way to do this?
I would create a Command in the class the you actually want the event. Then bind the Button Command to it. You can create your own Command or use something like a DelegateCommand