I am creating buttons dynamically for a user-based app. Now I have to tell the new form what text to apply to the buttons via parameters to the form, the form then creates the buttons. Now I have an issue - the events for these buttons: What is the best mechanism to get the button click events through. I cannot access the form from the originating form, and I can only pass simple data types (and arrays).
My first thought is to use a code to reffer to the appropriate method in a static class - basically, pass an array of ints through with the names of the buttons and their onclick handler calls one method - handle(int code) -> where code is used in a giant switch statement to call the appropriate method.
But I doubt this is the best mechanism. I would prefer to create a listener of some sort that simply listens for button clicks, and should the click be unhandled, determine which button was clicked and manage it from there.
I have looked at the observer pattern and I am not entirely convinced this is the best one to follow. The problem is not that there is no solution, the problem is that I want the BEST solution.
This is in C# for monodroid - but the impact of this information should be minimal.
Thanks
Not sure to fully understand what's actually your problem, but here's how you should deal with dynamic controls and event handlers:
Button myNewButton = new Button { Text = "MyCaption" };
myNewButton.Click += (sender, e) =>
{
((Button)sender).Text = "New text here!";
// Another logic could be put here
};
If it was WPF i'd use Commanding but i don't know if it's available for monofroid.
You may look at http://www.codeproject.com/KB/dotnet/EventBroker.aspx
Currently I have two options:
Use reflection - pass a method name to the button and that button can then invoke a method based on the string value passed. Then simply create a static class where all button methods are kept.
Use a switch statement - since I can have delegates that take parameters (one of them being a SENDER object) I can easily send the sender object to a method containing a switch statement which performs an action based on that object.
In my research I have determined that the former (reflection) is preferred, espcially since the number of buttons is rather large.
REFS:
http://embeddedgurus.com/stack-overflow/2010/04/efficient-c-tip-12-be-wary-of-switch-statements/
Large Switch statements: Bad OOP?
Method Factory - case vs. reflection
Related
This might sound weird, but I am just experimenting with the thought of it. I was wondering about subscribing functions to different classes. So i have a base or static location where my method is held, and without relying on inheritance, am i able to subscribe that function to an object?
For example:
Action class has a method class SendKeys
I have three objects called Textbox and Button and Textarea
Realistically i don't want them all to have access to SendKeys function, just Textbox, and Textarea. But i also don't want to copy paste the SendKeys code over and over again.
I could create a static class that takes the data and the two objects will call that static class, but that just seems like extra work and i would be creating the function anyways in order to call an external function.
The best solution i have is to just copy paste code. but i was wondering if i could subscribe specific functions. Its like the opposite of what an event and delegate can do right? Cause the subscription requires code in the class of the subscriber. I kind of think i want partial classes? I am not sure. Thoughts?
A deeper dive into the issue:
I have a bunch of different elements to work with here are some basic ones, it goes deeper when you take into account custom elements:
Button
Textbox
Textarea
MultiSelect
SingleSelect
RadioButtons
Checkboxes
MenuItems
PasswordTextboxes
ETC
Each one of these would have their own actions that can be applied. For example they all would have the same properties like GetAttribute or GetCssValue but i don't want to be sending keys to a checkbox, so i dont want to have the ability to have that function when creating inheritance. BUT, i do want other objects to have those functions. The code is lengthy and a bunch of copy pasting code is ugly. I was hoping i can subscribe functnions to objects. So i can say something like Actions.Click(Textbox) or Textbox.Click or w.e but i cannot do Actions.SendKeys(button, "fdsaf") or Button.SendKeys("fdsaf")
I've been wondering a lot how to have an object act different situationally.
To clarify what I'm wondering:
I want to make a menusystem, and I want to have a "button" class. But the button should behave different depending on what kind of button it is.
One button may close to program, another may start the game, a third may enter settings.
(I was thinking of parsing methods as arguments, but then you still have to write a lot of different methods somewhere in your code)
How do you do this with OOP in mind? I could hardcode the very basic functions of a simple menu using enums and switchcases, but I would want to know if it could be avoided.
I want to avoid things like delegates because games aren't eventbased in such fashion, and also switch-cases, large if/else statements because they are really ugly.
Is there a way to make objects behave like this?
What are other alternatives to making menus, trying to avoid the switch-cases for the commonly used enum. (Not disallowing enums)
I want to avoid things like delegates because games aren't eventbased in such fashion
Aren't they, though? A button click is an event, regardless of whether or not it's a game or a web application. It's by definition something happening that you'd like to react to, such as a button press. What happens when a button is clicked should be loosely coupled from the button in the UI, for the reasons you already encountered (large switch/if-elses are a pain) among others. A C# event field seems like the perfect fit, for this particular case anyway.
At some point, you create the settings button, somewhere, somehow. Why not wire up the event there? Something along the lines of:
class Button
{
public Button(string label) {}
public event Action Clicked;
}
class Program
{
public static void Main(string[] args)
{
var settingsButton = new Button("Settings");
settingsButton.Clicked += () =>
{
// open settings view
};
}
}
I'd avoid things like inheritance for this problem as it adds unnecessary complexity for the wrong reasons. You should (probably) use inheritance if the overriding class changes or supplements the behavior of the class it extends (a logical progression would be object extended by Component extended by Button extended by ToggleButton) but not to create a class hierarchy that's very much tied to how your UI is built up. If you change settings access to a dropdown menu instead of a button press, you don't want to be tied to a SettingsButton class; you want to be simply able to change which event triggers the desired behavior, in this case pulling down the dropdown menu.
Being a beginner in C# I am having problem in a specific implementation. I need to compute two data in real time by which I mean ki the output shows as soon as the inputs are provided with no click of button necessary.
- For example I have a Text Box where if a type a number 5 gets added to it and the output shows in a Label. The label automatically updates when more numbers are typed in real time.
How do I achieve this?
Thanks !
Before explaining the specifics, it's important to point out that from the code's perspective there isn't much difference between clicking a button or responding to the TextBox's event. Here's what I mean.
In addition to calling code procedurally from within your own methods like this:
void MyMethod(argument)
{
...Other Code...
DoSomething(argument);
...Other Code...
}
.Net also allows you to attach method calls to Events. Events are just references to delegates(I'll leave it up to you to research delegates), but they allow you to asynchronously execute your code based on external interaction.
In your question you say that you want to perform a calculation without making the user click a button. Before going into how you'll accomplish that, lets think about what you'd do if there were a button. Chances are you'll drag & drop a button onto the designer surface, then double click it. Behind the scenes you'll suddenly have a method that looks something like this:
void button_ButonClick(object sender, ClickEventArgs args)
{
DoSomething();
}
So you'll go and populate the new method's body with your calculation logic. Under the hood you've actually just had the designer hook that new method up to the Button's click event. So in your case, whether you're adding the calculation logic to a button click or the TextBox's TextChanged event, you're actually doing almost the same thing.
Just for reference, here's the MSDN documentation for TextBox's TextChanged event .
OK I will give it a shot :)
Assume two textboxes and a label on a form.
Each textbox has a text_changed event handler, i.e. if you type something in either text box, the event handler code is called and there you can access the text of each textbox and transform the text into two numbers.
Then you compute the 2 numbers as per your rules and the result is displayed in the label.
This is a very simplified explanation! There must be validation of the inputs in the textboxes to ensure the data format is correct.
Ask more questions if this is not clear enough.
I want to fill an updatepanel with new dynamic controls in response to a button click.
However, I also want to be able to access the values of these dynamic controls in response to an event in one of the controls.
Specifically, I want the button to bring up two dropdownmenus. One of the menus (or both if need be) is in another update panel. I want the first menu in the update panel to change its data in response to a value getting selected in the other menu.
I think my problem is that when I cause a postback with one dropdownmenu I lose the other dropdownmenu because I created it in the button_click handler.
I know I should create dynamic controls in the Page_Init method (or so ive heard) but I only want the controls to show up if the button is clicked. There are other buttons on the page which need to create a different set of dynamic controls.
Thanks.
There are a lot of ways you can handle this, and which approach to take really depends on your project's requirements and your available resources.
The smoothest way to do it that would generally provide the best user experience would be to use a Javascript technique to hide and show controls as the page required them. JQuery is the library I would recommend for this. On the most basic level, you simply wire the control's activation (such as a button_click event) and hide or show a div containing the dynamic content as necessary, like so:
$("#control").show();
// and
$("#control").hide();
Alternatively, you can do this in C# by using the Visible property on many of the normal web controls for ASP.NET. The usual code-behind approach would look something like this:
private void btnControl_Click(object sender, EventArgs e)
{
var dynamicControl1 = FindControl("dynamicControl1");
dynamicControl.Visible = false; // or true, as the case may be
}
This particular approach is mostly attached to code-behinds, though, which I would encourage you to avoid if possible. They are practically impossible to test and will make projects a pain to work in. You can use a similar approach in the MVC3 framework, of course, it will just be a little different how you send and receive the control you are setting to not be visible. The other benefit this has that is kind of nice is that if something is set to not be visible, it tends not to even be displayed in the HTML generated by the templating engine (YMMV depending on the engine, but I know this is true in Razor). So someone viewing the source of your webpage won't be able to see inactive controls, which may or may not be something that appeals to you.
EDIT: I see the problem is less to do with how to display these things, and more with how to create and read them back given on-the-fly input.
I'm sure there's a way to do this with Javascript (which would more than probably be the cleanest and best way to do this), but I'm not good enough with JS to know the answer to that one. The way you would handle this in ASP.NET is make the div you're going to add controls to server-side (by using runat='server', then add what you need there. Again, the trivial code-behind approach would be something like:
private void btnControl_Click(object sender, EventArgs e)
{
foreach(var checkBoxChecked in chkBoxes.Where(x => x.Checked))
{
div.Controls.Add(new WebControl()) // or whatever the heck else it is you need.
}
}
This presumes that you have an IEnumerable<CheckBox> to iterate over, of course. You may also want an IList<WebControl> to keep track of all the junk you're adding. You will also need to make sure the CSS is applied properly to the div for the controls you're adding. And again, code-behinds are pretty awful and I use the example only because it'd be easy to spin up in a project to test for yourself.
I have 3 buttons on my Data Entry form, OK, APPLY, CANCEL.
This form is used to edit a doctor's details, things like first name, phone # etc...
I have one object doctorObj which at any given time is either empty (a new doctor) or an object pulled from a Linq query.
I deep clone the doctorObj to EditCopyDoctor which is of the same type but used for form editing (so if Cancel is hit, the database do not need to update).
What I want to achieve is observe the EditCopyDoctor for changes against the original doctorObj so
If(doctor.Changed() && doctor.IsNotNew)
{
ApplyButton.Enabled = true;
}
else
{
ApplyButton.Enabled = false;
}
So I thought writting an event to trigger when something changed on EditCopyDoctor is the best way to do it but I'm not sure how.
I can of course put the ApplyButton.Enabled code in the TextChanged events from the form but I was wondering if there are any quicker ways to do this, I don't really want to do this as there are 10+ textbox and other controls.
Since your "Doctor" type sounds like it's generated by LINQ to SQL/Entities you should find that it already implements the INotifyPropertyChanged interface. Therefore, you should just need to watch the PropertyChanged event and act accordingly.