I currently started to "port" my console projects to WinForms, but it seems I am badly failing doing that.
I am simply used to a console structure:
I got my classes interacting with each other depending on the input coming from the console.
A simple flow:
Input -> ProcessInput -> Execute -> Output -> wait for input
Now I got this big Form1.cs (etc.) and the "Application.Run(Form1);"
But I really got no clue how my classes can interact with the form and create a flow like I described above.
I mean, I just have these "...._Click(object sender....)" for each "item" inside the form.
Now I do not know where to place / start my flow / loop, and how my classes can interact with the form.
Pretty straightforward, actually (though I can sympathize with your confusion)...
1. Input
Have a TextBox and a Button. When the user clicks on the button, treat whatever's in your TextBox as your input.
2. Process Input
In a console app, the user is unable to do anything while you're processing input. The analogue to this in a Windows Forms app is to disable the mechanism by which the user can supply input. So, set your TextBox.Enabled = false and Button.Enabled = false.
3. Execute
Run whatever method you want to execute.
4. Output
Have some kind of message displayed on the form. This could be simply another TextBox, or a RichTextBox... whatever you want.
5. Wait for Input
Once your method from step 3 has executed, you've displayed the output in part 4, you can go ahead and re-activate your mechanism for accepting input: TextBox.Enabled = true and Button.Enabled = true.
So basically your code should like something like this:
void myButton_Click(object sender, EventArgs e) {
try {
myInputTextBox.Enabled = false;
myButton.Enabled = false;
var input = ParseInput(myInputTextBox.Text);
var output = ExecuteMethodWithInput(input);
myOutputTextBox.Text = FormatOutput(output);
} finally {
myInputTextBox.Enabled = true;
myButton.Enabled = true;
}
}
Basically, you can have your form provide a set of controls for inputting data (ie: one or more TextBox controls). If you have a button that the user clicks, and you want to process, just double click on teh button. This will give you an event handler like:
private void button1_Click(object sender, EventArgs e)
{
// Process Input from TextBox controls, etc.
// Execute method
// Set output (To other controls, most likely)
}
That's it - the "loop" goes away, since the standard Windows message pump takes its place.
Related
Hi im hoping someone can assist im still new to programming and this is a noob question but i have created a Visual studio - C# (Windows Form Application) and now the question reads to Create a void method for each of my buttons i created in the form and telling me even what to name the method.
but on my research The void keyword is used in method signatures to declare a method that does not return a value.
LinkToAddresses () will be my void method for address the (button), so my question is do i just put in this void method and its going to do nothing?
im just going to link the full question maybe im just really not understanding this>?
''
The below form will represent the main form from which the user will navigate to the other forms. Meaning each button should be linked to the appropriate form. E.g. If button Manage Addresses is clicked the form managed addresses should be displayed. The Exit button should successfully terminate the program.
Create a void method for each button and name them as follow: LinkToAddresses (), LinkToCustomers (), LinkToDrivers (), LinkToStatus (), and LinkToFreight (). The methods should be called under the appropriate button. For the exit button create a void method named AppExit () this should terminate the program.
''
I would appreciate any help or guidance, thank you in advance.
Visual studio usually handles the button actions easily. Just place the buttons on your form, then rename the buttons to LinkToAddresses, LinkToCustomers, LinkToDrivers, LinkToStatus, LinkToFreight and AppExit. Then simply just double click on the each button and visual studio will create a void method for their click event.
using System;
using System.Windows.Forms;
namespace YourApp
{
public partial class FormMain : Form
{
private FormManagedAddresses formManagedAddresses = null;
public FormMain()
{
InitializeComponent();
}
private void LinkToAddresses_Click(object sender, EventArgs e)
{
if (formManagedAddresses != null)
{
formManagedAddresses.Close();
}
formManagedAddresses = new FormNews();
formManagedAddresses.Show();
}
private void AppExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
The closest thing to a buttons function, is the Click Event Handler. While specific names vary based on Display technology (WinForms, WPF/UWP, ASP.Net), that is the general pattern for Graphical User Interfaces. It is called event driven programming. Even things that have a different programm flow like Games and Web Applications usually try to imitate it.
The signature of a event is given during its definition and must be strictly followed. Usually void NameOfTheEvent(object sender, SampleEventArgs e).
A return type of void is extremely common with events. If there is to be any output, that usually is handeled via a property in the Event Args or by directly doing stuff with the other GUI Elements.
If you want a button to do nothing, you just never give it a event handler. Every single button you ever used, was given a implicit or explicit event handler to do exactly what it did. If you want it to conditionally do nothing, either disable the Button so it can not be clicked, or put a proper if-statement into the event Handler.
A advanced topic would be the command pattern, where there is a bunch of commands in code behind. And each button, menu item and key combination is meerely a way to trigger said command - a representation for hte user to call the command.
You can share a single event across any number of Elements. AS you can see above, the pattern for events includes object sender as argument. This means you can check if it is a specific Button instance that called the event. Or even "unpack" the specific button, do look at stuff like Display String, Tag to get data from it. However, as a general rule retrieving data from the GUI is a bit frowned - ideally the GUI should only represent the data in the backend.
I am developing a Kinect game in C# where the user needs to click 2 buttons at the same time by hovering over one button with each hand.
However, with my current code, when the user hovers with one hand over a button, the other buttons get disabled and the other hand can only click when the first hand stops hovering over a button.
To solve this, I'm thinking of queuing the second click while the first click is being processed. To do this, I have used the following code based on this link
private Queue<System.Windows.Controls.Button> Button_Queue = new Queue<System.Windows.Controls.Button>();
private bool isProcessing = false;
private void Button_Click((object sender, RoutedEventArgs e){
if(isProcessing){
Button_Queue.Enqueue(this);
}
else
{
isProcessing = true;
// code here
isProcessing = false;
while(Button_Queue.Count > 0){
Button_Queue.Dequeue().PerformClick();
}
}
However, the Button_Queue.Enqueue(this) line shows the error
"The best overloaded method match for Queue.Enqueue has invalid
arguments."
I'm guessing this is because the button click event cannot be queued in a queue declared with the type Button.
Do you have any suggestions for how to create this queue of button click events or another way to handle multiple clicks from the user?
You don't need to queue the event. If isProcessing is true, then the other button was already clicked, so you can handle the event for both button clicks from that point on.
You could measure the time between the two clicks, to work out if it validates as a "two buttons clicked at the same time" event.
Have you considered a more low-level approach? The first thing that came to mind was to create two hot areas instead of buttons and monitor whether the user's hands are inside those areas at the same time.
It is unclear to me why another button is disabled when you hand is hovering over another object. Without seeing the code, I would say that you are doing something that would cause that -- and there is no reason to.
Additionally, you should be using interaction concepts centered around a gesture system and not something that is written for a mouse/keyboard input. Using regular UI objects and interacting with them in ways that parallel traditional inputs will only serve to confuse the users.
Have a look at the following two examples, which use a "hover-to-click" and a "press-to-click" interaction
Basic Interaction, for SDK 1.6
Control Basics, for SDK 1.7 (in Kinect for Windows Developer Toolkit)
In both cases, you are using a hit test on custom controls to handle events. Here is an example of a hit test function I use in one of my apps:
private void HitTestHand(HandPosition hand)
{
// quick fix to null pointer exception on exit.
if (Application.Current.MainWindow == null)
return;
Point pt = new Point(hand.X, hand.Y);
IInputElement input = Application.Current.MainWindow.InputHitTest(pt);
if (hand.CurrentElement != input)
{
var inputObject = input as DependencyObject;
var currentObject = hand.CurrentElement as DependencyObject;
// If the new input is a child of the current element then don't fire the leave event.
// It will be fired later when the current input moves to the parent of the current element.
if (hand.CurrentElement != null && Utility.IsElementChild(currentObject, inputObject) == false)
{
// Raise the HandLeaveEvent on the CurrentElement, which at this point is the previous element the hand was over.
hand.CurrentElement.RaiseEvent(new HandInputEventArgs(HoverDwellButton.HandLeaveEvent, hand.CurrentElement, hand));
}
// If the current element is the parent of the new input element then don't
// raise the entered event as it has already been fired.
if (input != null && Utility.IsElementChild(inputObject, currentObject) == false)
{
input.RaiseEvent(new HandInputEventArgs(HoverDwellButton.HandEnterEvent, input, hand));
}
hand.CurrentElement = input;
}
else if (hand.CurrentElement != null)
{
hand.CurrentElement.RaiseEvent(new HandInputEventArgs(HoverDwellButton.HandMoveEvent, hand.CurrentElement, hand));
}
}
Notice that an event is being fired on the element below the hand cursor. Examples of these elements can be found in the two links above (the HoverDwellButton is what I use with the above code sample).
Two events on two different elements, or the same element, can fire at any time with this. You can easily keep track of which user is over which button, if that button is in the process of being pressed, or if it has been pressed.
The key to all this is not using a UI paradigm that isn't designed for gesture systems! Don't try to shoehorn the keyboard/mouse event structure into a gesture based system -- it will only cause you more pain in the long run and cause your users confusion.
I've a form that navigates webpage and access data. It looks like something below.
private void LoginButton_Click(object sender, EventArgs e)
{
if(LoginButton.Text == Login)
{
LoginButton.Text = "Logging in...";
....
...
Login process goes here...
..
if(Login Successed)
{
LoginButton.Text ="Download";
}
else
{
LoginButton.Text = "Login";
}
}
else if(LoginButton.Text==Download)
{
Download data here...
}
}
Same button(And same event too), doing two process and seems like different events with a label.
1) If there any problem like inefficiency run?
2) Any alternate ways to do this like different flag schemes?
3) Any method to have with more than one event for same button to achieve same idea?
Thanks.
1) If there any problem like inefficiency run?
Button clicks run at human time. You can burn half a billion cpu instructions without inconveniencing the user.
2) Any alternate ways to do this like different flag schemes?
Using the Text property of the button is fragile, your code will break when somebody decides to change the button text or when you localize your app to another language. A simple private bool field in your class is much better.
3) Any method to have with more than one event for same button to achieve same idea?
No. You could of course use two buttons, placed on top of each other and one of them always hidden. Makes localization much simpler and you'll get that bool field for free.
like Daniel A. White said
have two buttons
may be on some event like oncreate/onload do check..jst a pseudo code
if process is login then
do
//then showLoginButton
btnlogin.visible
else
//download
btndonload.visible
inside the login button
if(Login Successed)
{
btndonload.visible
}
else
{
LoginButton.Text = "Login";
}
this may be better with two buttons then single..and cleaner also
Write custom event handlers for the mouseClick
Write separate methods for login and download.
Register your custom event handlers to the button click event
I assume there is some logic that decides that the button text should be "download" or "login". At that point, set the button text of course, but also register the appropriate event handler.
This will allow you to have a single button that does anything
protected void Login_MouseClickHandler (object obj ,MouseClickEventArgs e) {
// login logic
// this would be the logic you say is "inside the login button"
}
protected void Download_MouseClickHandler (object obj ,MouseClickEventArgs e) {
// download logic
}
// pseudo code
// note that there is only one button
if process is login then
theButton.text = "login"
theButton.MouseClick += new MouseClickEventHandler(Login_MouseClickHandler)
else
button.text = "download"
theButton.MouseClick += new MouseClickEventHandler (Download_MouseClickHandler)
end if
Software Design Thoughts
Easier to extend. We don't need another button for every new thing to do
Separation of Concerns - All login code, for example, is in a separate method that does only login stuff.
Change is isolated and minimized. Writing new, separate methods is less error prone than in-lining that code in your if else structure. And consequently the if else structure is kept simple and comprehensible.
It is generally a bad idea use the text as the state. Ideally, you should have 2 buttons that fire different events and call out the main logic to a presenter in the MVP pattern.
Use control containers such as Panel and GroupBox. You can have a whole bunch of Panels for controls in different states.
I need to create a user control in C#.Net, which can be added to the application without being visible - just like the FolderBrowserDialog. It's a new window which I'll be using often so I think this is the right way. The window will be opened by envoking the showDialog-Method as known from the other dialog.
Any Idea?
Thanks and regards,
Daniel
Since all these "invisible" controls derive from Component class, you should start by reading the MSDN article on it: http://msdn.microsoft.com/en-us/library/system.componentmodel.component.aspx.
simply set Visible to false or isn't this what you're asking for ?
A UserControl is by definition not a Form; I think what you really want is a Component. That said, couldn't you really just create a new Form class that has the functionality you want? Whenever you want to display it, create a new instance and call ShowDialog. Or, if you want to preserve state, add an instance as a class member to your parent form, call its Show method whenever you want to display it, and add an event handler to its FormClosing event to check:
if (e.CloseReason == CloseReason.UserClosing)
and, if so,
e.Cancel = true;
Hide();
(This last part is to prevent errors if the user closes the form and then tries to display again after it's been disposed.)
I think more information may be needed, but if your crating a custom user control, the control should have a .Visible property. The follow is an example of how a button can be located on the form but hidden from a user.
button.Visible = true; // shows the button
button.Show(); // Shows the button
button.Visible = false; // hides the button
button.Hide(); // Hides the button
While the button may still be on the form/control, it will not be interactible by the user. You can still perform programmatic control on the button, but essentially it is not a user control while it is 'hidden'. If you want there to be a sort of hidden button that the user can click you will need to do other things to obtain this but It doesn't should like that is what you want.
This show/hide thought process sounds a lot like pains and confusion leftover from classic VB. The old form methods of show and hide, etc., were confusing and often left me as a developer in a position to not know whether an object existed or if was merely invisible. And checking was only trivial if you used On Error Goto to prevent a null reference. So right off I would advise not to think in terms of visibility unless you are doing something with a web page and need to maintain space and state.
First, create a Windows form and add it to your project, assuming that is the type of project that you are describing. Decorate the form with the proper controls, and where applicable, create properties to allow public access to the control values. Also set the DialogResult property of the buttons that either "OK" or "Cancel" the form. Give it an appropriate border style of either Fixed3D or FixedDialog. Maybe also set the property for where you want the form to appear on startup -- center parent, center screen, Windows default, etc. The event handlers for both "OK" and "Cancel" should invoke this.Close(); to close the window.
From the calling point in the code, here's some hypothetical code to get you going in the right direction. Write something like this in the place where you want to invoke your Dialog.
int intResult = 0;
string strResult = null;
MyDialogForm frm = new MyDialogForm();
frm.Title = "Select an Item";
frm.SomeProperty = 0;
frm.SomeOtherProperty = true;
if (frm.ShowDialog() == DialogResult.OK)
{
intResult = frm.Result;
strResult = frm.StringResult;
}
else if (frm.ShowDialog() == DialogResult.Cancel)
{
// User clicked the cancel button. Nothing to do except maybe display a message.
MessageBox.Show("Canceled Task");
}
...
// Somewhere further on down, but within scope, simply repeat
// what you just did, but without having to reinstantiate the
// form Window. But if you make it that far within the same
// scope, this method might be too busy and may need to be
// factored down.
So in short:
Scrap show/hide -- its not a good
practice.
Save the form data without
using an invisible form to save it;
that's the class's job.
If the UI requires a lot of flipping back and
forth between windows, check your
design for other alternatives for
solving the original problem. Maybe a design pattern such as MVC is for you, depending upon the size and complexity of your application.
Sound good?
You can put that control in a Panel. Set the panel height = 0 visible = false when you dont want to show the control.
And do the vice versa when you want to show it.
Derive from Control, not UserControl, and in the constructor set Visible = false.
Also create an event handler in the constructor.
VisibleChanged += new EventHandler(SetVisibleFalse);
Create a method named SetVisibleFalse.
private void SetVisibleFalse(object sender, EventArgs e)
{
if (Visible) Visible = false;
}
In the application I am working with, if the user changes the value in a cell that is say positive to negative and the value is supposed to be positive at all times, the application forces the positive value. Right now, when this happens there is no alert shown to the user.
I would like to show a little unobtrusive alert, like the one that shows up when a new mail arrives in outlook, or something similar, so that the user can be alerted that the application did something on her behalf.
I tried using the NotifyIcon class to do this. But the problem with that class seems to be that the timeout on it doesn't work as expected. I want to show this alert for not more than 2s and the BallonTipText lasts for longer than 10s.
Is there a .NET class for this purpose?
If not, is there an alternate way to do something like this?
Using a notification icon for this case seems wrong to me. The user's attention is, when entering something into a cell, on the cell. If you display the notification on the lower right of the screen the user is very likely to miss it, or worse, it disrupts his work flow.
You might instead consider adding a balloon tip to the cell the user is editing. Kinda like the balloon tip Windows Explorer is showing on Vista and Windows 7 on renaming a file when you try entering a character that is disallowed in file names:
I have had this problem in the past. I gather that the timeout problem is because the operating system fixes a minimum value of 10 seconds and a maximum value of 30 seconds (or something like that).Edit Oh and this doesn't include time that a user is idle.Edit
I have used the following code in the past to get around this.
Just to clarify
Declare a public variable, say called ballonTipActive with a value of 0.
Insert a timer control disabled with 100ms delay and create an event from BalloonTipShown from the notifyicon control.
Then
private void ptNotifyIcon_BalloonTipShown(object sender, EventArgs e)
{
timer1.Enabled = true;
balloonTipActive = 0;
}
private void timer1_Tick(object sender, EventArgs e)
{
balloonTipActive++;
if (balloonTipActive == 40)
{
ptNotifyIcon.Visible = false;
ptNotifyIcon.Visible = true;
balloonTipActive = 0;
timer1.Enabled = false;
}
}
Setting the visible property to false then true gets rid of the balloon.