I am trying to create a custom event to trigger an animation in Silverlight. Although the event is getting triggered, the animation is not working. The following is the relevant code:
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
MyEvent += new ChangedEventHandler(UserControl_MyEventHandler);
/* Other stuff */
}
private void UserControl_MyEventHandler(object sender, RoutedEventArgs e)
{
MessageBox.Show("MyEventHandler has been called");
}
public delegate void ChangedEventHandler(object sender, RoutedEventArgs e);
private event ChangedEventHandler MyEvent;
private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (MyEvent != null)
MyEvent(this, e);
}
}
}
The XAML code is as follows:
<UserControl
...
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" mc:Ignorable="d"
x:Class="SilverlightApplication1.MainPage" MouseLeftButtonDown="UserControl_MouseLeftButtonDown">
<Grid x:Name="LayoutRoot" Background="White">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MyEvent">
<ei:GoToStateAction StateName="Highlighted"/>
</i:EventTrigger>
</i:Interaction.Triggers>
...
</Grid>
</UserControl>
Current, the message box containing "MouseLeftButtonDown" is getting displayed but the animation is not getting called. The animation did get called when the EventTrigger EventName was MouseLeftButtonDown instead of MyEvent. Please help me out. Thanks.
You can set SourceName in EventTrigger if you want to trigger on event of some control.
I guess, in your case in code behind:
VisualStateManager.GoToState(this [or some other object with Highlighted state], "Highlighted", false);
Related
I have added a click event on the calendar control. But with my implementation, this event don't work.
My code in Cal.cs control:
#region click
public static RoutedEvent ClickEvent =
EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Cal));
public event RoutedEventHandler Click
{
add { AddHandler(ClickEvent, value); }
remove { RemoveHandler(ClickEvent, value); }
}
protected virtual void OnClick()
{
RoutedEventArgs args = new RoutedEventArgs(ClickEvent, this);
RaiseEvent(args);
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
OnClick();
}
#endregion
XAML code :
<Calen:Cal x:Name="Calendar" Margin="0,50,0,0" Click="Calendar_Click"/>
C# code :
private void Calendar_Click(object sender, RoutedEventArgs e)
{
string t = "";
}
I don't found any solution. I don't know why this code don't work correctly.
Can you help me with this problem please ?
You need to set the DataContext to point to the class that contains the code behind.
<UserControl>
DataContext="{Binding RelativeSource={RelativeSource Self}}">
</UserControl>
This is necessary because unfortunately, by default, the DataContext is not set up correctly in WPF.
For more info on DataContext, see ReSharper WPF error: "Cannot resolve symbol "MyVariable" due to unknown DataContext".
I have created a UserControl that has a command (DeleteCommand) inside:
public partial class TestControl : UserControl
{
public static RoutedCommand DeleteCommand = new RoutedCommand();
private void DeleteCommandExecute(object sender, ExecutedRoutedEventArgs e)
{
}
private void DeleteCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
public TestControl()
{
InitializeComponent();
CommandBinding deleteCommandBinding = new CommandBinding(DeleteCommand, DeleteCommandExecute, DeleteCommandCanExecute);
this.CommandBindings.Add(deleteCommandBinding);
}
}
I have put this UserControl inside a Window:
<Window x:Class="TestRoutedCommand.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestRoutedCommand"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Fire event" Margin="156,29,205,254" Command="{x:Static local:TestControl.DeleteCommand}" />
<local:TestControl Margin="126,135,135,46"/>
</Grid>
</Window>
There is also a Button which is using the DeleteCommand. My problem is that this button is always disabled and the DeleteCommandCanExecute handler is never called, although e.CanExecute is always set to true.
I have tried to call:
CommandManager.InvalidateRequerySuggested();
but nothing happens. The event is never fired. Maybe I am doing the CommandBinding wrong.
What I want to achieve is that when the user clicks on the button that the DeleteCommandExecute handler is fired. My goal is to create commands for my MenuButtons which will trigger some methods in my UserControls which can be deep in the Visual Tree.
Slightly change your XAML:
<Grid>
<Button Content="Fire event" Margin="156,29,205,254" Command="{x:Static local:TestControl.DeleteCommand}" CommandTarget="{Binding ElementName=Control1}" />
<local:TestControl x:Name="Control1" Margin="126,135,135,46"/>
</Grid>
CommandTarget says where to find needed handlers.
working in WPF with C# I am generating an event from a view MyView and what I need to do is to handle it in the associated view model class MyViewModel.
I am using caliburn.micro to solve and this is the code in synthesis:
<UserControl x:Class="MyView"
xmlns:cal="http://www.caliburnproject.org"
DataContext="MyViewModelInstance"
cal:Message.Attach="[Event CancelEvent]=[Action CancelButton_Click_MyViewModelHandler($source,$eventArgs)]">
<Grid>
<Button Click="CancelButton_Click"> </Button>
</Grid>
</UserControl>
In the code behind I handle the click event generating a CancelEvent:
public partial class MyView : UserControl
{
public event EventHandler CancelEvent;
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
if(CancelEvent!=null)
{
CancelEvent(sender,e);
}
}
}
In the class MyViewModel I defined the function
public void MyViewMOdelHandler(Object sender, EventArgs arg)
What I need to do is to handle the CancelEvent in MyViewModelInstance, using the code above results as no one is subscribed to the CancelEvent (CancelEvent == null) so that the CancelEvent handler in MyViewModelInstance is not invoked.
Does anybody know a solution to the problem? (caliburn is not mandatory)
Thanks in advance.
-Z-
I think the solution is easy. In your view:
<UserControl x:Class="MyView"
xmlns:cal="http://www.caliburnproject.org"
DataContext="YourViewModel"
<Grid>
<Button Click="CancelButton_Click" cal:Message.Attach="[Event Click]=[Action MyViewModelHandler($source,$eventArgs)]">> </Button>
</Grid>
CancelButton_Click in code behind can be removed.
In your viewmodel:
public class YourViewModel : PropertyChangedBase
{
public void MyViewModelHandler(Object sender, EventArgs arg)
{
}
}
Is there any reason you're not directly attaching the click event of the button? as that would be the simplest solution.
Looking at your example it would seem the Message.Attach is specifiing a method that doesn't exist.
If the method on the view model is
public void MyViewModelHandler(Object sender, EventArgs arg)
then the attach syntax would be
cal:Message.Attach="[Event CancelEvent]=[Action MyViewModelHandler($source,$eventArgs)]"
In my user control I have a button that, when clicked, would raise a custom Routed Event. I've attempted to raise it, but it doesn't get fired in the MainWindow.xaml.
Xaml for the button in UserControl:
<Button x:Name="PART_Add" Content="+" Grid.Column="3" Margin="0,0,0,0" Style="{DynamicResource dTranspButton}" Click="btnAdd_Click"/>
UserControl C# code:
//AddClick Event
public static readonly RoutedEvent AddClickEvent = EventManager.RegisterRoutedEvent("AddClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(dCB_Props));
public event RoutedEventHandler AddClick
{
add { AddHandler(AddClickEvent, value); }
remove { RemoveHandler(AddClickEvent, value); }
}
void RaiseAddClickEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(dCB_Props.AddClickEvent);
}
protected void OnAddClick()
{
RaiseAddClickEvent();
}
//objects events
private void btnAdd_Click(object sender, System.Windows.RoutedEventArgs e)
{
RaiseAddClickEvent();
}
Xaml Code for the UserControl Instance in MainWindow.xaml:
<local:dCB_Props x:Name="cb1" Margin="41.166,0,36.19,25" VerticalAlignment="Bottom" Height="30" Width="141" AddClick="dCB_Props_AddClick">
<local:dCB_Props.Items>
<ComboBoxItem Content="item1"/>
</local:dCB_Props.Items>
</local:dCB_Props>
C# Code that should get fired in MainWindow.xaml.cs:
private void dCB_Props_AddClick(object sender, System.Windows.RoutedEventArgs e)
{
MessageBox.Show("This Works");
}
You need to call
RaiseEvent(new RoutedEventArgs(AddClickEvent));
Why this code in WPF does not work ?
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("yes");
}
private void Form1_Load(object sender, EventArgs e)
{
button1.PerformClick();
}
I need to command.
To use the windows form application's style, you need to write the following extension method:
namespace System.Windows.Controls
{
public static class MyExt
{
public static void PerformClick(this Button btn)
{
btn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
}
}
now you can use it for any button, assuming a button called "btnOK":
btnOK.PerformClick();
Wait.. there is simple way. if your button name is button1 and button1 click event already subscribed,you will just call that event like
button1_Click(this,null);
Instead of PerformClick() use RaiseEvent()
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("yes");
}
private void Form1_Load(object sender, EventArgs e)
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(Button.ClickEvent);
button1.RaiseEvent(newEventArgs);
}
I think the shortest and most efficient solution to your problem would be simply done in one line.
button1.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
That should work for WPF C#
Good practice in WPF is using commands. It improves testability and separates UI and business logic.
First you may try RoutedUICommand.
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self ="clr-namespace:Test"
Title="MainWindow"
Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="{x:Static self:MainWindow.RoutedClickCommand}"
CanExecute="CommandBinding_CanExecute"
Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<Grid>
<Button Content="Test" Name="Btn1" Command="{x:Static self:MainWindow.RoutedClickCommand}"/>
</Grid>
In code behind file we have to define RoutedClickCommand and Execute|CanExecute handlers:
public static ICommand RoutedClickCommand = new RoutedUICommand("ClickCommand", "ClickCommand", typeof(MainWindow));
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("ololo");
}
So, when you need button logic ("button1.PerformClick();" in your sample), just put next line:
MainWindow.RoutedClickCommand.Execute(null);
As for me, I preffer another way which supposes carry command into presentation model. Composite Application Library (Prism) helps me with its DelegateCommand class. Then command definition in presentation model looks like:
private DelegateCommand<object> _clickCommand;
public ICommand ClickCommand
{
get
{
if (this._clickCommand == null)
{
this._clickCommand = new DelegateCommand<object>(p =>
{
//command logic
},
p =>
{
// can execute command logic
});
}
return this._clickCommand;
}
}
And view XAML and code behind:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self ="clr-namespace:Test"
Title="MainWindow"
Height="350" Width="525">
<Grid>
<Button Content="Test" Name="Btn1" Command="{Binding ClickCommand}"/>
</Grid>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Model = new SampleModel();
}
protected SampleModel Model
{
get
{
if (this.Model.ClickCommand.CanExecute())
{
this.Model.ClickCommand.Execute();
}
return (SampleModel)this.DataContext;
}
set
{
this.DataContext = value;
}
}
}
Next code calls command in view bypassing clicking on button:
if (this.Model.ClickCommand.CanExecute())
{
this.Model.ClickCommand.Execute();
}
An excerpt from Adam Nathans WPF Unleashed, recommended by this blog.
Imho one of the best, if not the best WPF references around.
var bap = new System.Windows.Automation.Peers.ButtonAutomationPeer(someButton);
var iip = bap.GetPattern(System.Windows.Automation.Peers.PatternInterface.Invoke)
as System.Windows.Automation.Provider.IInvokeProvider;
iip.Invoke();
Because PerformClick is a method on WindowsForms Button control:
http://msdn.microsoft.com/en-us/library/system.windows.forms.button.performclick.aspx
Not on the WPF Button control:
http://msdn.microsoft.com/en-us/library/system.windows.controls.button_methods.aspx
To automate a button click, you might like to take a look at the UI automation framework:
http://msdn.microsoft.com/en-us/library/ms747327.aspx