I created a CustomButton, inherited from Button class. Then I created some event, like GotFocus, LostFocus, etc.
public sealed class CustomButton : Button
{
public CustomButton()
{
this.DefaultStyleKey = typeof(CustomButton);
}
protected override void OnApplyTemplate()
{
this.GotFocus += CustomButton_GotFocus;
this.LostFocus += CustomButton_LostFocus;
base.OnApplyTemplate();
}
private void CustomButton_LostFocus(object sender, RoutedEventArgs e)
{
//some common behavior code
}
private void CustomButton_GotFocus(object sender, RoutedEventArgs e)
{
//some common behavior code
}
}
Then I used this CustomButton in some pages. But in some specified pages, I don't want the CustomButton excute the GotFocus, LostFocus event.
So how to override these event in the specified pages?
I tried add GotFocus, LostFocus event in the specified pages, but it will finally run the common code behavior in CustomButton.
For the requirement, you could make a DependencyProperty to control the GotFocus or LostFocus event could be excuted or not.
For example:
public class CustomButton : Button
{
public CustomButton()
{
this.DefaultStyleKey = typeof(Button);
Current = this;
}
private static CustomButton Current;
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
public bool EnableDetected
{
get { return (bool)GetValue(EnableDetectedProperty); }
set { SetValue(EnableDetectedProperty, value); }
}
// Using a DependencyProperty as the backing store for EnableDetected. This enables animation, styling, binding, etc...
public static readonly DependencyProperty EnableDetectedProperty =
DependencyProperty.Register("EnableDetected", typeof(bool), typeof(CustomButton), new PropertyMetadata(0, new PropertyChangedCallback(OnValueChanged)));
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue == true)
{
Current.GettingFocus += Current_GettingFocus;
}
else
{
Current.GettingFocus -= Current_GettingFocus;
}
}
private static void Current_GettingFocus(UIElement sender, GettingFocusEventArgs args)
{
}
}
Usage
<local:CustomButton Content="Btn" EnableDetected="true" />
you can "take off" the events out of the CustomButton by iterating the page controls:
foreach(var cb in this.Controls.OfType<CustomButton>())
{
cb.GotFocus -= CustomButton.GotFocus;
cb.LostFocus -= CustomButton.LostFocus;
}
I believe this should work.
Related
I´ve started learning only recently so this is a newbie question.
Maybe someone could help me out in regards to what I´d have to do differently for my code to work.
In short: I have a class that inherits from INotifyPropertyChanged (which I´v tried to implement according to MSDN). When I press a button I want to change a variable in this class which in turn should raise a PropertyChanged Event. When the event is raised some code should be executed.
My ValueChanged class:
public class ValueChange : INotifyPropertyChanged
{
public ValueChange()
{
_size = 1;
}
private int _size;
public int Size
{
get
{
return _size;
}
set
{
_size = value;
OnPropertyRaised("Size");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyRaised([CallerMemberName] string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
My event listeners:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
ValueChange test = new ValueChange();
test.Size = 10;
}
private void PropertyChanged(object sender, PropertyChangedEventArgs args)
{
switch (args.PropertyName)
{
case "Size":
// txtbox is just some textbox in my UI
txtbox.Text = "some text";
// This is merely a placeholder as I´d like to be able to execute any code in here
break;
}
}
}
There are a few issues with the code.
You are creating a new instance of the ValueChange class every time you click.
You are not subscribing to PropertyChanged event.
Although this will fix your code, is there a reason you are using PropertyChanged here instead of executing your code directly in the Button_Click event handler? PropertyChanged is usually used when binding, it is rarely used directly as you are doing here.
public partial class MainWindow : Window
{
ValueChange test = new ValueChange();
public MainWindow()
{
test.PropertyChanged += PropertyChanged;
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
test.Size = 10;
}
private void PropertyChanged(object sender, PropertyChangedEventArgs args)
{
switch (args.PropertyName)
{
case "Size":
// txtbox is just some textbox in my UI
txtbox.Text = "some text";
// This is merely a placeholder as I´d like to be able to execute any code in here
break;
}
}
}
I want to disable button(or other control) when user can't raise event. What is the best way to do this? View handles that or presenter should pass value by property in view and then view will update control's state.
For example if previous query is not finished user shouldn't start new.
Option 1:
interface IView
{
event EventHandler Event;
}
class View : IView
{
private readonly Button _button;
public event EventHandler Event;
public void button_Click(object sender, EventArgs e)
{
_button.Enabled = false;
if(Event != null)
{
Event(this, EventArgs.Empty);
}
_button.Enabled = true;
}
}
class Presenter
{
public void View_Event(object sender, EventArgs e)
{
// code...
}
}
Option 2:
interface IView
{
event EventHandler Event;
bool CanRaiseEvent { set; }
}
class View : IView
{
private readonly Button _button;
public event EventHandler Event;
public bool CanRaiseEvent
{
set
{
_button.Enabled = value;
}
}
public void button_Click(object sender, EventArgs e)
{
if (Event != null)
{
Event(this, EventArgs.Empty);
}
}
}
class Presenter
{
private readonly IView _view;
public void View_Event(object sender, EventArgs e)
{
_view.CanRaiseEvent = false;
// code...
_view.CanRaiseEvent = true;
}
}
I know that i should check in presenter query's status before executing next query but I want to inform view that user shouldn't even try.
Two 'litmus' tests I use for MVP design are: 1) Is the logic testable? and 2) Could I replace the concrete view and the application still work?
From this perspective, option 2 looks the more attractive.
I have a WPF project in Windows 2012 in which I need to load some information in the Window Loaded event. I need to do this in the View Model rather than in the CodeBehind, though. I am attempting to use the following code:
In my xaml:
<interactivity:Interaction.Behaviors>
<behaviors:WindowLoadedBehavior LoadedCommand="{Binding WindowLoadedCommand}" />
</interactivity:Interaction.Behaviors>
In my View Model:
private DelegateCommand _WindowLoadedCommand;
public DelegateCommand WindowLoadedCommand
{
get
{
return _WindowLoadedCommand;
}
private set
{
_WindowLoadedCommand = value;
}
}
public ShellViewModel()
{
WindowLoadedCommand = new DelegateCommand(WindowLoadedAction);
}
protected void WindowLoadedAction()
{
...
}
My attached behavior:
public class WindowLoadedBehavior : Behavior<FrameworkElement>
{
[SuppressMessage("Microsoft.StyleCop.CSharp.MaintainabilityRules", "SA1401:FieldsMustBePrivate", Justification = "Dependency Property. Allow public.")]
public static DependencyProperty LoadedCommandProperty = DependencyProperty.Register("LoadedCommand", typeof(ICommand), typeof(WindowLoadedBehavior), new PropertyMetadata(null));
public ICommand LoadedCommand
{
get { return (ICommand)GetValue(LoadedCommandProperty); }
set { SetValue(LoadedCommandProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += AssociatedObject_Loaded;
}
protected override void OnDetaching()
{
AssociatedObject.Loaded -= AssociatedObject_Loaded;
base.OnDetaching();
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
if (LoadedCommand != null)
LoadedCommand.Execute(null);
}
}
The OnAttached, AssociatedObject_Loaded and LoadedCommand get are all firing, but the LoadedCommand set is not firing and, obviously, the WindowLoadedCommand isn't firing. Any clue what I can do to get this working?
There are a few options. A couple of them listed here:
how to call a window's Loaded event in WPF MVVM?
However, in the off chance that you or anyone else cares that you are spending several hours to complete a task that should have taken 30 seconds, you might want to try this instead.
public MainWindow()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
ShellViewModel.Instance.WindowLoadedCommand.Execute(null);
}
I have a button which is rdbAuto, when form is load, rdbAuto will be checked, I want to set the focus (boundary) for this radiobutton, how can I do that?
You can override the RadioButton control with something like this
public class SuperRadioButton : RadioButton
{
private bool showFocusCues = false;
protected override void InitLayout()
{
this.GotFocus += (sender, args) =>
{
showFocusCues = true;
};
this.LostFocus += (sender, args) =>
{
showFocusCues = false;
};
}
protected override bool ShowFocusCues
{
get
{
return showFocusCues;
}
}
}
This will force the boundary to be shown whenever the radio button has focus.
Use this control instead of the standard radio button and then call the Focus method in the Form_Shown event
private void Form1_Shown(object sender, EventArgs e)
{
superRadioButton1.Focus();
}
Is there a way to give a User Control custom events, and invoke the event on a event within the user control. (I'm not sure if invoke is the correct term)
public partial class Sample: UserControl
{
public Sample()
{
InitializeComponent();
}
private void TextBox_Validated(object sender, EventArgs e)
{
// invoke UserControl event here
}
}
And the MainForm:
public partial class MainForm : Form
{
private Sample sampleUserControl = new Sample();
public MainForm()
{
this.InitializeComponent();
sampleUserControl.Click += new EventHandler(this.CustomEvent_Handler);
}
private void CustomEvent_Handler(object sender, EventArgs e)
{
// do stuff
}
}
Aside from the example that Steve posted, there is also syntax available which can simply pass the event through. It is similar to creating a property:
class MyUserControl : UserControl
{
public event EventHandler TextBoxValidated
{
add { textBox1.Validated += value; }
remove { textBox1.Validated -= value; }
}
}
I believe what you want is something like this:
public partial class Sample: UserControl
{
public event EventHandler TextboxValidated;
public Sample()
{
InitializeComponent();
}
private void TextBox_Validated(object sender, EventArgs e)
{
// invoke UserControl event here
if (this.TextboxValidated != null) this.TextboxValidated(sender, e);
}
}
And then on your form:
public partial class MainForm : Form
{
private Sample sampleUserControl = new Sample();
public MainForm()
{
this.InitializeComponent();
sampleUserControl.TextboxValidated += new EventHandler(this.CustomEvent_Handler);
}
private void CustomEvent_Handler(object sender, EventArgs e)
{
// do stuff
}
}