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
Related
I'm developing my first application in WPF with the pattern MVC and I have a question.
I have created a usercontrol from type Grid to made a custom title bar. This grid contains a X button and I want to associate this button to a command.
My grid in XAML:
<Grid x:Class="Views.TitleBarView"
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"
Style="{DynamicResource TitleStyleGrid}"
x:Name="barView">
<Label x:Name="labelAppName" Style="{DynamicResource TitleStyleLabel}" Content="Title"/>
<Button x:Name="bttnClose" Style="{DynamicResource ButtonStyleCloseWindow}" Command="{Binding CloseCommand}"/>
<Button x:Name="buttonMinimize" Style="{DynamicResource ButtonStyleMinimizeWindow}" Command="{Binding MinimizeCommand}"/>
</Grid>
The C# view:
public partial class TitleBarView : Grid
{
public TitleBarView()
{
InitializeComponent();
TitleBarViewModel tvm = new TitleBarViewModel();
tvm.RequestClose += (s, e) => this.Close();
tvm.RequestMinimize+= (s, e) => this.Minimize();
DataContext = tvm;
}
private void Close()
{
Window.GetWindow(this).Close();
}
private void Minimize()
{
Application.Current.MainWindow.WindowState = System.Windows.WindowState.Minimized;
}
}
The C# viewModel:
public class TitleBarViewModel : ViewModelBase, IRequestMinimizeViewModel, IRequestCloseViewModel
{
private RelayCommand minimizeCommand;
protected RelayCommand closeCommand;
public event EventHandler RequestMinimize;
public event EventHandler RequestClose;
#region MinimizeCommand
public ICommand MinimizeCommand
{
get
{
if (minimizeCommand == null)
{
minimizeCommand = new RelayCommand(Minimize);
}
return minimizeCommand;
}
}
private void Minimize()
{
RequestMinimize(this, null);
}
#endregion
#region CloseCommand
public ICommand CloseCommand
{
get
{
if (closeCommand == null)
{
closeCommand = new RelayCommand(Close);
}
return closeCommand;
}
}
protected void Close()
{
RequestClose(this, null);
}
#endregion
}
I saw that it's not recommended to set a DataContext on a userControl. And when I do this, I can't change the close command. For example I want that when the main windows calls command close it calls Application.Current.Shutdown(); instead of Application.Current.Shutdown();
I know that I have something wrong but I'm too confuse to solve it. Can you explain me how to create command for userControl ? (Or just tell me what I'm doing wrong)
Thank you
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)]"
I am dynamically creating a GroupBox and trying to assign the MouseLeftButtonDown event to it to perform some action when the user left-clicks on it. This is what I've tried:
public MyClass()
{
tagGroupBox.MouseLeftButtonDown += new MouseButtonEventHandler(tagGroupBox_MouseLeftButtonDown); //generates error: "tagGroupBox_MouseLeftButtonDown does not exist in the current context"
}
private void tagGroupBox__MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Left click event triggered");
}
There are __ (double underscores) in handler method.
void tagGroupBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
}
This works for me:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
GroupBox g = new GroupBox();
g.MouseLeftButtonUp += new MouseButtonEventHandler(g_MouseLeftButtonUp);
MainGrid.Children.Add(g);
}
void g_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
System.Diagnostics.Debugger.Break();
}
}
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="MainGrid">
</Grid>
</Window>
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);
I'm quite a novice with C# and a complete newbie regarding WPF. Probably it's a very basic question and piece of cake for the pros. Please bear with me.
I need to display a dynamic textblock with text changed in run time without additional triggers such as button clicks and so. For some reason (my insufficient understanding of the concept obviously) textblock stays empty.
Xaml is as simple as it can be:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Grid>
<TextBlock Text="{Binding Path=Name}"/>
</Grid>
</Window>
And the code behind it simplified as well:
using System.ComponentModel;
using System.Threading;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Client client = new Client();
client.Name = "Michael";
Thread.Sleep(1000);
client.Name = "Johnson";
}
}
public class Client : INotifyPropertyChanged
{
private string name = "The name is:";
public event PropertyChangedEventHandler PropertyChanged;
public string Name
{
get
{
return this.name;
}
set
{
if (this.name == value)
return;
this.name = value;
this.OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, e);
}
}
}
Thanks in advance,
Ceres
In order for the binding to work you need to set the DataContext of the window to the object you want to bind to, in this instance the client object.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Client client = new Client();
// Set client as the DataContext.
DataContext = client;
client.Name = "Michael";
Thread.Sleep(1000);
client.Name = "Johnson";
}
This should cause the TextBox to successfully update.
Just to point out that using Thread.Sleep() in the loaded event causes the program to hang for a second on startup, a better idea would be to use the WPF DispatcherTimer to create the 1 second delay.
Hope that helps!