I have a WPF Custom Control inherited from Button.
How do I programatically get the custom control to capture the Click Event (so that I can record the action and do some internal work)
(basically I want to catch the event and set a certain property to a certain value) and make this part of the classes standard functionality.
From my understanding the custom control should be able to catch it's own even and do some work.
Help appreciated
try one of the overrides
public class CustomButton : Button {
protected override void OnPreviewMouseDown(MouseButtonEventArgs e) {
base.OnPreviewMouseDown(e);
}
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) {
base.OnPreviewMouseLeftButtonDown(e);
}
}
I have realised why Ihad a problem.
I could not see the Click event
This was because I was not explicit enought in my class declaration:
I put
public class StateButton : Button
obviously picked the wrong button .. as
public class StateButton : System.Windows.Controls.Button
works
Then I just override the event
Thanks
Related
I have a number of views in my Windows Phone 8 app that share a lot of similarity, so I created a base class to contain the common logic. In general, this approach has worked great, but with one limitation - I am unable to move the common event handling logic into the base class. Here is the simplified version of what I am trying to achieve:
The base class defines a method which my sub-classes should use to handle a button click event in their respective application bars.
public class BaseView : PhoneApplicationPage
{
protected void OnButtonClick(object sender, EventArgs e)
{
MessageBox.Show("Button Pressed");
}
}
The XAML for the inheriting view looks like this (showing only the relevant part). Note the ApplicationBarIconButton's event handler. My intention is that the OnButtonClick method, defined in the base view, is called.
<base:BaseView
x:Class="EventHandlersInBaseClassBugRepro.MainPage"
xmlns:base ="clr-namespace:EventHandlersInBaseClassBugRepro"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
..... >
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsMenuEnabled="False">
<shell:ApplicationBarIconButton
IconUri="/Assets/Tiles/FlipCycleTileSmall.png"
Text="Click"
Click="OnButtonClick"/>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
The application compiles, but at runtime I am getting this exception:
{System.Windows.Markup.XamlParseException: Failed to assign to property 'Microsoft.Phone.Shell.ApplicationBarIconButton.Click'. [Line: 22 Position: 23]
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at EventHandlersInBaseClassBugRepro.MainPage.InitializeComponent()
at EventHandlersInBaseClassBugRepro.MainPage..ctor()}
I saw a similar question here Silverlight: Can I set an event to a base class event handler in XAML?. My interpretation of the answer suggests that the approach I am using should work, yet the exception.
Is what I am trying to do possible?
Remember Events are a delegate that should only be invoked in the class that declared them.
In your scenario you havent declared an Event in the BaseView.
Also mark the OnButtonClick invoke method as Virtual so that it can be overridden in derived classes. Try
public class BaseView : PhoneApplicationPage
{
public event EventHandler ButtonClicked;
public virtual void OnButtonClick(object sender, EventArgs e)
{
MessageBox.Show("Base Button Click");
}
}
In your derived class .cs you will need to override OnButtonClick like this
public override void OnButtonClicked(object sender, EventArgs e)
{
// do derived class logic here
MessageBox.Show("Derived class hit");
// calls BaseView event invoke method
base.OnButtonClicked(sender, e);
}
Hope that helps
I'm working in WPF to create a ListView component. The items in the list are based on another user control that reacts to MouseLeftDown events. The List also reacts to SelectionChanged events.
Right now, if I mouse down on any item on the list and move the cursor, the other items I pass along react to the SelectionChanged event (which is expected since the selection is changing as per the Mouse Down event in List view). I need to be able to disable this reaction when its down through a drag-to-scroll behavior, but to keep it active when the user selects an item on the list.
Does anyone have any ideas how this can be achieved?
Thanks everyone,
RK
I believe one of the ways that could help you is to implement your own handlers of MouseUp and MouseDown events of your items to select item on MouseUp instead of MouseDown. You could start from a sample like this:
public class MyListView : ListView
{
protected override DependencyObject GetContainerForItemOverride()
{
return new MyListViewItem();
}
}
public class MyListViewItem : ListViewItem
{
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
return;
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
}
}
I have a button inside my UserControl. I have three instances of this UserControl on the same page.
How can I expose the click event of the button inside such that I can assign different events for each instance of my UserControl.
I think this is similar to concept behind exposing DependencyProperty but I don't understand how to do it for events.
Thanks.
I normally add an event of the same name (and same parameters) to the user control and subscribe to the child control's original event, so I can pass the event on:
public partial class ClickEventControl : UserControl
{
public event EventHandler<RoutedEventArgs> Click;
public ClickEventControl()
{
InitializeComponent();
}
private void aButton_Click(object sender, RoutedEventArgs e)
{
if (Click != null)
{
Click(sender, e);
}
}
}
I would also be interested if there is a more general way of doing it.
For a very specific reason I want to select ListViewItems on mouse button up, not actually on mouse button down. I want this behaviour to be embedded in the control. Is it possible to achieve this? can anyone give hint?
Yes it's definitely possible using attached properties. Define an attached property called SelectOnMouseUp and when it's set to true, hook to your ItemsContainerGenerator events to discover when a new item container is added. Then when you get an event for a new item container, hook into its PreviewMouseDown and ignore it (set e.Handled to true), and hook into its MouseUp event and perform the selection (set IsSelected to true).
Aviad P.'s answer is a good one and a clever use of attached properties, but I tend to use a different technique most of the time:
Subclass ListViewItem.
Override OnMouseLeftButtonDown and OnMouseRightButton to do nothing.
Override OnMouseLeftButtonUp / OnMouseRightButtonUp to call base.OnMouseLeftButtonDown / base.OnMouseRightButtonDown.
Subclass ListView.
Override GetContainerForItemOverride() to return your ListViewItem override
This seems easier to me than subscribing to ItemContainer events and adding handlers dynamically.
This is what it looks like:
public class MouseUpListViewItem : ListViewItem
{
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {}
protected override void OnMouseRightButtonDown(MouseButtonEventArgs e) {}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
}
protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
{
base.OnMouseRightButtonDown(e);
}
}
public class MouseUpListView : ListView
{
protected override DependencyObject GetContainerForItemOverride()
{
return new MouseUpListViewItem();
}
}
I like this technique because there is less code involved.
How do you get two unrelated controls to raise the same custom event? All examples I have seen so far have an event defined within a single control, should I be taking a different approach?
Eg. I'd like to raise a custom bubbling event from an OnFocus handler for a button and a textbox.
First off let me say your question doesn't make it clear that you don't want to use the existing UIElement.GotFocusEvent, but I'll assume you know about it and have your reasons for not using it.
You can always register a custom event on a static class, and raise it wherever you want. The Keyboard class does with all of its events (e.g. Keyboard.KeyDownEvent).
public static class RoutedEventUtility
{
public static readonly RoutedEvent MyCustomEvent = EventManager.RegisterRoutedEvent("MyCustomEvent", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RoutedEventUtility));
}
You raise the event just like you would any other RoutedEvent.
RoutedEventArgs args = new RoutedEventArgs(RoutedEventUtility.MyCustomEvent);
RaiseEvent(args);
If you want another class to own the event as a public field then you will need to add an owner.
public class MyCustomControl : Control
{
public static readonly RoutedEvent MyCustomEvent = RoutedEventUtility.MyCustomEvent.AddOwner(typeof(MyCustomControl));
}