Adding event handler in style - silverlight

I have 8 HyperlinkButton on my silverlight application.
I want to call method HyperlinkButtonClick_Event when each of them will be clicked.
Can i do it on style ?
If 'no' so how can i do it without adding the method explicitly on each of the HyperlinkButton instance ?

How about using something like this in your style:
<Setter Property="Command" Value="{Binding ClickCommand}" />
And using a Command, such as a DelegateCommand, with an Execute action replacing your HyperlinkButtonClick_Event code.
This is also obviously going to require you to have the datacontext set correctly for each of your buttons...
The DelegateCommand in it's VERY simplest form:
public class DelegateCommand : ICommand
{
private Func<object, bool> canExecute;
private Action<object> executeAction;
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
{
this.executeAction = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
this.executeAction(parameter);
}
public bool CanExecute(object parameter)
{
return this.canExecute(parameter);
}
}
You can find implementations of this everywhere, from SO to MSDN...

public class MyCheckBox : CheckBox
{
public MyCheckBox()
{
this.Click += new RoutedEventHandler(MyCheckBox_Click);
}
void MyCheckBox_Click(object sender, RoutedEventArgs e)
{
CheckBox chk = (sender as CheckBox);
}
}
<foo:mycheckbox ................/>
Define your own class and use the foo:mycheckbox in style file.

Related

Handle an event that is inside user control in list view

I have a list of user control and each user control have two buttons, and when I click on them, something must happen, but I want to handle this event not inside the user control, I want to handle the events inside the main page
So, How can I catch the events that fired by the selected item user control of list view?
user control code behind:
public sealed partial class TestingUerControl : UserControl
{
public TestingUerControl()
{
this.InitializeComponent();
}
public event EventHandler FirstButtonEvent;
public event EventHandler SecondButtonEvent;
private void firstButton_Click(object sender, RoutedEventArgs e)
{
//Some stuff of code
FirstButtonEvent?.Invoke(this, new EventArgs());
}
private void secondButton_Click(object sender, RoutedEventArgs e)
{
//Some stuff of code
SecondButtonEvent?.Invoke(this, new EventArgs());
}
}
main page xaml markup:
<ListView x:Name="listUserControl"
Width="100"
Header="400">
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:MyModel">
<userControl:TestingUerControl/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I used this statement:
((TestingUerControl)listUserControl.SelectedItem).FirstButtonEvent += OnFirstButtonEvent;
but this doesn't work I can cast the SelectedItem to MyModel class only
So How can I reach to "FirstButtonEvent" and "SecondButtonEvent" of selected user control of list view
The way with commands and MVVM is preferable, but you can also work with custom RoutedEvent instead of Event:
public sealed partial class TestingUerControl : UserControl
{
public TestingUerControl()
{
this.InitializeComponent();
}
public static readonly RoutedEvent FirstButtonEvent = EventManager.RegisterRoutedEvent(
nameof(FirstButton), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TestingUerControl));
public event RoutedEventHandler FirstButton
{
add { AddHandler(FirstButtonEvent, value); }
remove { RemoveHandler(FirstButtonEvent, value); }
}
private void firstButton_Click(object sender, RoutedEventArgs e)
{
//Some stuff of code
RaiseEvent(new RoutedEventArgs(TestingUerControl.FirstButtonEvent));
}
private void secondButton_Click(object sender, RoutedEventArgs e)
{
//See first btn
}
}
and then in XAML just assign an event handler:
<ListView x:Name="listUserControl" Width="100" Header="400">
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:MyModel">
<userControl:TestingUerControl FirstButton="OnFirstButton_Click"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Use MVVM:
public class TestCommand : ICommand
{
Action<object> _execute;
Func<object, bool> _canExecute;
public TestCommand(Action<object> execute)
: this(execute, DefaultCanExecute)
{
}
public TestCommand(Action<object> execute, Func<object, bool> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
if (canExecute == null)
{
throw new ArgumentNullException("canExecute");
}
this._execute = execute;
this._canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public bool CanExecute(object parameter)
{
if (_canExecute != null)
{
return _canExecute(parameter);
}
else
{
return false;
}
}
public void Execute(object parameter)
{
_execute(parameter);
}
private static bool DefaultCanExecute(object parameter)
{
return true;
}
}
public class MyModel
{
public MyModel()
{
FirstButtonCmd = new TestCommand(OnFirstButtonCmd);
SecondButtonCmd = new TestCommand(OnSecondButtonCmd);
}
public ICommand FirstButtonCmd{get;set;}
public ICommand SecondButtonCmd{get;set;}
private void OnFirstButtonCmd()
{
//click first button
}
private void OnSecondButtonCmd()
{
//click second button
}
}
TestingUerControl.xaml
<Button Click={Binding FirstButtonCmd}></Button>
<Button Click={Binding SecondButtonCmd}></Button>
TestingUerControl.xaml.cs
public sealed partial class TestingUerControl : UserControl
{
public TestingUerControl()
{
this.InitializeComponent();
}
}

Input Binding CommandParameter Bind to Window

I want to have a window level KeyBinding with command paramter as window itself.
e.g.
<KeyBinding Command="{Binding CloseCommand}" CommandParameter="{Binding ElementName=mainWindow}" Key="Esc"/>
Binding works, but paramter comes in as null. What's the work around?
Following is my Command:`
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute,
Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("Action excute is null");
_execute = execute;
_canExecute = canExecute;
}
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
Actually this working for me - but i am using the RelayCommand<FrameworkElement> of [MVVM Light Toolkit1.
<Window.InputBindings>
<KeyBinding Command="{Binding MyCommand, ElementName=MainRoot}" CommandParameter="{Binding ElementName=MainRoot}" Key="Esc"/>
</Window.InputBindings>
In my case the Command comes from a DependencyProperty, but that shouldn't make a big difference.
public RelayCommand<FrameworkElement> MyCommand
{
get { return (RelayCommand<FrameworkElement>)GetValue(MyCommandProperty); }
set { SetValue(MyCommandProperty, value); }
}
// Using a DependencyProperty as the backing store for MyCommand. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyCommandProperty =
DependencyProperty.Register("MyCommand", typeof(RelayCommand<FrameworkElement>), typeof(MainWindow), new PropertyMetadata(null));
public MainWindow()
{
InitializeComponent();
MyCommand = new RelayCommand<FrameworkElement>(DoSthYo);
}
public void DoSthYo(FrameworkElement fwE)
{
var x = fwE;
}
So because this is working - i think its your Command that does not support CommandParameter maybe.
My advice is to use a RelativeSource in your CommandParameter binding:
<Window.InputBindings>
<KeyBinding Command="{x:Static local:CloseWindowCommand.Instance}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Key="Esc" />
</Window.InputBindings>
In this way your binding can be independant from the name of your Window.
Then you can create a static command for closing each window of your application:
public class CloseWindowCommand : ICommand
{
public static readonly ICommand instance = new CloseWindowCommand();
public event EventHandler CanExecuteChanged;
private CloseWindowCommand()
{
}
public bool CanExecute(object parameter)
{
return (parameter is Window);
}
public void Execute(object parameter)
{
Window win;
if (CanExecute(parameter))
{
win = (Window)parameter;
win.Close();
}
}
}
I hope it can help you.

Button stays disabled - DelegateCommand not re-evaluating CanExecute handler

Problem: Buttons never gets enabled.
<Button Name="btnCompareAxises"Command="{Binding CompareCommand}"
Content="{Binding VM.CompareAxisButtonLabel}"
IsEnabled="{Binding VM.IsCompareButtonEnabled}">
</Button>
ViewModel constructor:
this.CompareCommand = new DelegateCommand(CompareCommand, ValidateCompareCommand);
The problem seems to be related to the CanExecute eventhandler of the registered Command of the button.
The CanExecute handler returns false when the application loads.
This is fine, as the conditions are not met initially.
The canExecute handler only runs on application startup or when the button is clicked. You cannot click a disabled button, so the button stays disabled forever if the initial value returned form the CanExecute handler is false!
Question:
Do I have to enable the button again, only using the command bound to it.
Something like, hey command please reevaluate if the conditions for this buttons are met ?
Why sits the IsEnabled property under section Coercion and not under local?
The command:
public class DelegateCommand : ICommand
{
private readonly Func<object, bool> canExecute;
private readonly Action<object> execute;
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
public void RaiseCanExecuteChanged()
{
this.OnCanExecuteChanged();
}
protected virtual void OnCanExecuteChanged()
{
var handler = this.CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
Solved:
I had to adapt the DelegateCommand class to make it work:
I have added CommandManager.RequerySuggested to the public CanExecuteChanged Event property.
Now it will automatically re-evaluate the CanExecute method of the command when soemthing changes in the UI!
public class DelegateCommand : ICommand
{
private readonly Func<object, bool> canExecute;
private readonly Action<object> execute;
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
/// CommandManager
/// Go to the "References" part of your class library and select "Add Reference".
/// Look for an assembly called "PresentationCore" and add it.
public event EventHandler CanExecuteChanged
{
add
{
_internalCanExecuteChanged += value;
CommandManager.RequerySuggested += value;
}
remove
{
_internalCanExecuteChanged -= value;
CommandManager.RequerySuggested -= value;
}
}
event EventHandler _internalCanExecuteChanged;
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
public void RaiseCanExecuteChanged()
{
this.OnCanExecuteChanged();
}
protected virtual void OnCanExecuteChanged()
{
var handler = this._internalCanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
Removed this from the button:
IsEnabled="{Binding VM.IsCompareButtonEnabled}"
The binding here is not necessary, as the CanExecute handler will take care of the enabled/disabled state of the button!

Simple MVVM binding issue

I have one textbox and one button. The Button Command should change the property which is binded to the TextBox.
But I don't see any visual changes after command execution.
I think it easy question related to wpf binding
Please help me with this issue
Source of app:
<UserControl.DataContext>
<local:SampleViewModel />
</UserControl.DataContext>
<Grid>
<StackPanel>
<TextBox Height="23" Width="120" Text="{Binding MyName}" />
<Button Content="Click" Command="{Binding ButtonCommand}" />
</StackPanel>
</Grid>
ViewModel:
Private _myName As String
Public Property MyName As String
Get
Return _myName
End Get
Set(value As String)
_myName = value
OnPropertyChanged("MyName")
End Set
End Property
Public _buttonCommand As DelegateCommand
Public ReadOnly Property ButtonCommand As DelegateCommand
Get
Return If(_buttonCommand IsNot Nothing, _buttonCommand,
New DelegateCommand(AddressOf Execute, AddressOf CanExecute))
End Get
End Property
Private Sub Execute()
MyName = "Executed"
End Sub
Private Function CanExecute() As Boolean
Return True
End Function
Public Event PropertyChanged As PropertyChangedEventHandler
Private Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Do the following:
1.
Class MainWindow
Implements INotifyPropertyChanged
2 . In Public Sub New() make sure you write Me.DataContext = Me to set the DataContext
Note: Ignore step 2 if you're using a ViewModel and setting it in XAML
3 . Modify the ProperyChanged like this:
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Only after implementing INotifyPropertyChanged correctly will the Binding correctly refresh the MyName property after the PropertyChanged event
Here is a code that works with your exact XAML (I took the DelegateCommand implementation from http://wpftutorial.net/DelegateCommand.html ) Sorry it's C#, i'm really not into VB :D
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute,
Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public virtual bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public virtual void Execute(object parameter)
{
_execute(parameter);
}
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
public class SampleViewModel : INotifyPropertyChanged
{
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public DelegateCommand _buttonCommand;
public DelegateCommand ButtonCommand
{
get
{
if (_buttonCommand == null)
{
_buttonCommand = new DelegateCommand(Execute);
}
return _buttonCommand;
}
}
public void Execute(object o)
{
MyName = "executed";
}
public string MyName { get { return _myName; } set { _myName = value; OnPropertyChanged("MyName"); } }
private string _myName;
}

How should I move a WPF Window using MVVM?

This is probably overkill on the MVVM pattern but it's new to me and I'm interested to see if it is possible.
If I attach to the MouseMove event for a Window and do DragMove, I can move a bordeless window. Can I achieve this by some other method in MVVM or should I just accept adding this code to the Window's codebehind?
This is pure UI logic and doesn't belong in a ViewModel. The only reason you wouldn't want to put this in your code-behind would be for re-use and that is better solved with a custom Window derived control.
Personally I think any solution using MVVM would not make this code any better. Also, this is typically something that's view related and hasn't got anything to do with the data you're displaying.
IMHO, unless this is something that effects your data (aka the Model) then it is View code and should be in the View's code-behind and not in the Model.
I'm going to actually answer your question. The answer is yes. I'm using Cinch to assist me in the event binding and view model creation. The solution uses DragMove, but not as part of the code-behind (which is what I believe you are asking).
Event binding in the XAML:
<Window
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cinchV2="clr-namespace:Cinch;assembly=Cinch.WPF"
...>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<cinchV2:EventToCommandTrigger Command="{Binding MouseLeftButtonDown}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid>
...
</Grid>
</Window>
In the ViewModel:
[ExportViewModel("MainViewModel")]
[PartCreationPolicy(CreationPolicy.NonShared)]
internal sealed class MainViewModel : ViewModelBase
{
public SimpleCommand<object, EventToCommandArgs> MouseLeftButtonDown { get; private set; }
[ImportingConstructor]
public MainViewModel(IUIVisualizerService uiVisualizerService)
{
...
MouseLeftButtonDown = new SimpleCommand<object, EventToCommandArgs>(OnMouseLeftButtonDown);
}
private static void OnMouseLeftButtonDown(EventToCommandArgs e)
{
((Window)e.Sender).DragMove();
}
}
Fairly simple, right? Any events that come from the UI contain the View as the sender. So, here, we simply call the method on the view within the event handler in the ViewModel.
The project I'm working on uses no code-behind (even if it is not recommended in MVVM).
I know that I am a little late to the question, but this is what I have been using for sometime now and it works like a charm.
DashboardViewModel viewModel;
public DashboardView()
{
InitializeComponent();
viewModel = new DashboardViewModel();
viewModel.RequestClose += (s, e) => Application.Current.Dispatcher.Invoke(this.Close);
viewModel.RequestMinimize += (s, e) => Application.Current.Dispatcher.Invoke(() => { this.WindowState = WindowState.Minimized; });
DataContext = viewModel;
}
and something like this in your viewModel
#region Public Event Handlers
public event EventHandler<EventArgs> RequestClose;
public event EventHandler<EventArgs> RequestMinimize;
#endregion
Using the ICommand interface...
#region ICommand Members
public ICommand CloseCommand { get; private set; }
public ICommand MinimizeCommand { get; private set; }
#endregion
Configure the commands...
private void SetupCommands()
{
CloseCommand = new RelayCommand(CloseApplication);
MinimizeCommand = new RelayCommand(MinimizeApplication);
}
Here is the RelayCommand class.
public class RelayCommand : ICommand
{
#region Private Readonly Properties
private readonly Action<object> executeCommand;
private readonly Predicate<object> canExecute;
#endregion
#region Constructors
public RelayCommand(Action<object> execute) : this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
this.executeCommand = execute;
this.canExecute = canExecute;
}
#endregion
#region Public ICommand Members
public bool CanExecute(object parameter)
{
return canExecute == null ? true : canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
executeCommand(parameter);
}
#endregion
}
And some example methods...
private void MinimizeApplication(object obj)
{
RequestMinimize(this, new EventArgs());
}
private void CloseApplication(object obj)
{
RequestClose(this, new EventArgs());
}
Hope this helps!
I know it's an old question. However I prepared another simple implementation. Use following behavior to make window moveable:
public class WindowMoveBehavior : Behavior<Grid>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
}
protected override void OnDetaching()
{
AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonDown;
base.OnDetaching();
}
private void AssociatedObject_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Window.GetWindow(AssociatedObject).DragMove();
}
}
Xaml example:
<Style x:Key="CustomWindowStyle" TargetType="{x:Type Window}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid>
<i:Interaction.Behaviors>
<behaviors:WindowMoveBehavior/>
</i:Interaction.Behaviors>
<!-- different controls and content -->
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
11 years passed, but maybe someone is still interested in case to drag window using MVVM. This tricky solution is based on window's property "Tag" - almost no one use it but it's time to find out it's strength :) So all you need is System.Windows.Interactivity nuget, no Cinch or events!
Xaml:
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<Window ... Tag="{Binding WindowTag}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding DragMoveWindowCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Let's find out your current window and move it. In ViewModel:
private object _windowTag;
public object WindowTag
{
get
{
return _windowTag;
}
set
{
_windowTag = value;
OnPropertyChanged("WindowTag");
}
}
private RelayCommand _dragMoveWindowCommand;
public RelayCommand DragMoveWindowCommand
{
get
{
return _dragMoveWindowCommand ??
(_dragMoveWindowCommand = new RelayCommand(obj =>
{
try
{
var window = WindowService.GetCurrentWindowByTag(WindowTag = 1);
window.DragMove();
}
catch (Exception ex)
{
}
}));
}
}
public static Window GetCurrentWindowByTag(object tag)
{
return (from Window w in App.Current.Windows
where w.Tag == tag
select w)?.FirstOrDefault();
}
Enjoy!)

Resources