Best way to pass values in C#/XAML - c#

I'm just getting started in C# and hope you can help me choose the best way to pass values. I'm doing an exercise building a calculator in Visual Studio. I need to pass/get values once buttons are clicked.
I can see that a (sloppy?) way to do this would be to create code for each button's click event. Doing that, I would be certain which button is pressed... then could call a method and pass it a hard-coded argument indicating the button's value. For example, "BtnEntry_Click(1)" when the one button is pressed.
Another way would be to grab the sender's name, then have a switch statement that checks the button's name and assigns the value. For example:
private void BtnEntry_Click(object sender, RoutedEventArgs e)
{
var buttonClicked = sender as Button;
switch (buttonClicked.Name)
{
case "btnOne":
// The one button was pressed, so pass 1
break;
case "btnTwo":
//The two button was pressed, so pass 2
break;
//etc .....
}
}
A third option would be to put the value into the button's tag property, then grab it from there.
Is there another option using the RoutedEventArgs? If so, can you offer example code?
Is there a best way from among the options above... or is there a better way to do this?
Thanks!
Note: An editor noted that this question is related to the one posted at this question. I feel this is a broader view, addressing more potential solutions, and also easier for "noobs" like me to understand. The other question has stuff about binding code, which makes it an unhelpful answer for me.
I did, however, come across this answer regarding commands, which expands on the idea offered by Drew Noakes and kidshaw. (Thanks!)
So, I would suggest keeping this as a separate question, since it offers an easier entry point than the other and also addresses more options.

Of the options you offer, the tag would be my preference. But since this is wpf, you can implement an mvvm solution where you have a command and supply a parameter to a viewmodel.
Typically mvvm has overhead that might deter its use in small apps, such as a calculator. But since you're a newbie and looking for options - it's worth doing small to learn it.

I'm not a fan of the Tag property because it is not typed. You might consider having a class inherit from Button, and have that class implement a property that exposes its underlying numeric value.

Related

WPF MVVM C# Input Bindings With TextBox key presses

I am currently stuck on an issue that I have been unable to find an answer for. It involves 'overriding' built-in TextBox keyboard functions using MVVM. Here's my issue:
I have a TextBox that the users enters text into during runtime. I'm looking to implement keyboard shortcuts, or input bindings with this TextBox. I started out by using what seems to be the standard ICommand interface based approach, which I implemented simply as:
<TextBox.InputBindings>
<KeyBinding Key="Up" Command="{Binding testCommand}" Modifiers="Ctrl" />
</TextBox.InputBindings>
The idea is that I execute the command associated with the ICommand property as set in the ViewModel. However, the TextBox class already contains a baked in function for CTRL+UP which, as you may know, moves the caret to the beginning of the TextBox entry field. This function executes in addition to my Command, resulting in my desired changes, but also the caret moving.
Before MVVM, I would simply use the PreviewKeyDown event in Code-Behind, detecting the desired key combinations and using
e.Handled = true;
to stop the TextBox from firing its built in Command. This isn't an optimal solution, however, as it probably violates MVVM principles. It would also be difficult to implement in tandem with InputBindings declared in XAML.
During my research, I found an article that describes using a class provided by Blend that allows for executing a Command based off an event, potentially allowing me to listen for the PreviewKeyDown event, which fires before the built-in functions, but this would mean that I would not be declaring my key bindings in XAML, as the syntax does not seem to support keypress specific conditions, or InputBindings. I would have to do all key combination processing logic in the ViewModel, which seems like something the View should be doing.
Further research has led me to an interesting new area which involves intercepting and replacing certain 'ApplicationCommands' with a Command that always returns false on CanExecute, effectively removing the function. I was able to locate a case where someone wanted to replace the default CTRL+Z functionality. An abridged version of the full question shows the basic idea:
textBox.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo,
UndoCommand, CanUndoCommand));
Research of this ApplicationCommands class led me to a few other classes, one of which relates more directly to my issue: ComponentCommands. MSDN describes that class as containing (among other things)
ComponentCommands.MoveToHome
which would fit my Ctrl+Up command's built-in function. Using the syntax in the SO question I linked previously, I could theoretically prevent that command from executing, which is a step in the right direction. However, I'm hoping to make the key combinations that trigger my Command in my ViewModel customizable via ViewModel properties that the InputBindings would be bound to in XAML. If I implemented this approach, it would mean that I could not know ahead of time which built in functions might conflict with the user's chosen key bindings.
This was naturally resolved for me before I switched to MVVM by handling the arguments in the event handler in Code-Behind, as mentioned previously. Any key combinations I wrote into the PreviewKeyDown event handler that I had a special action for set the e.Handled to true, effectively preventing any possible built-in command that would follow once the method finished from executing after the event handler finished.
Is there some way I could implement this functionality, using InputBindings declared in XAML? What are my options?
Some ideas:
Perhaps I could expose the event handler for PreviewKeyDown on my TextBox, and inside the method I iterate through all of the TextBox's InputBindings, looking for provided key combinations that match the provided key press, and if found, I execute the associated command and set e.handled to true? I'm not familiar with manipulating InputBindings from Code-Behind, so I'm not sure how practical this would be, or if it would place too much load on the application (imagine a user holding down a key). It also seems a bit strange in terms of organization to set it up this way. I could see a situation happening where the input bindings fire twice.
I could also make a list of all the built-in commands that I'd want to always have around, even if the user set a key combination that conflicted, and disable the rest. That seems like a bad idea, as it would be quite laborious, and also could mess with something I couldn't anticipate.
Perhaps there's a way that I could calculate which built-in commands would conflict with the current input bindings and disable those, to be calculated each time the user sets the bindings?
I'm still learning MVVM and WPF, so I suspect that I may be missing something obvious or simply looking at it the wrong way. Any help would be greatly appreciated.
Edit:
It has been suggested that my question is a duplicate of this one. I have reviewed the answer and determined that the approach used is definitely a step in the right direction. I could use the attached object to implement the PreviewKeyDown handling without losing functionality of InputBindings in XAML. However, I do have some concerns.
It seems that the resolution was to move the InputBindings to the UserControl, and implement an attached object that would handle PreviewKeyDown. I have multiple TextBoxes in my UserControl which will need their own set of InputBindings, some of which would conflict with one another should they be moved to the UserControl level.
I can only conclude that the reason it was moved away from the TextBox was that the attached object could not be applied directly to the TextBox for some reason. If I was to attempt this, would I have to create some encompassing element that had the attached object that would hold each TextBox? Why can't the TextBox use the attached object itself?

Change the auto-complete behaviour of a textbox

I have two doubts about the autocomplete feature of textboxes in C#.
First, I want to display the full list, not only the ones that start with the given text, and secondly I want to prevent the auto-complete of specific options (some are category titles).
I've been checking the textbox properties and there's nothing related to it, so probably the main question could be, Is there a way to modify / override the textbox events in order to handle the auto-complete actions? (I don't know if it applies to show the full list too)
I assume you're asking about a winforms textbox, as I dont think the WPF textbox supports autocomplete at all.
The base TextBox class will not support doing what you want, so you could in theory attempt to override all of the functionality in the TextBox class to do what you want, but the better idea would be to create a new custom control that inherits from TextBoxBase and implement the autocomplete behavior the way you want it.
I'm not sure about displaying the full list (perhaps a combobox or similar is more suited to this?) but you can definitely do something like this to swap which list of possible items can be displayed.
Another option, though one I like less, is to remove items you don't want to display at a given time from the collection dynamically, like this: textBox.AutoCompleteCustomSource.Remove("ACategoryTitle")
I could foresee that approach having many problems with trying to rebuild the list constantly. I would probably create a subclass of AutoCompleteStringCollection that wraps some LINQ code to nicely select the union of some lists and not others to display in the textbox.
I decided to build my own autocomplete tool with the help of a simple listbox and events, then I could achieve what I was expecting..
The CodingGorilla's answer probably leads to a better solution if you want something more decent, in my case for speed reasons I decided to do it that way but I'll mark his answer as the accepted in order to help other people who have the same doubt and they could consider that point..

Winforms: Short-cut key text without binding

Ok so there are many ways to go about fixing my problem. The title describes one.
The problem is that I have made an editor using a smart text box control (ScintillaNET) and I wish to implement an Edit -> Undo button on the menu that also displays its short-cut key in the text. Unfortunately I cannot simply bind it since it will result in the undo event being fired twice (once that the control does on its own, and once by me).
I still need the button to run the undo if it is clicked by the user (as opposed to the short-cut key).
There are 3 ways to fix this that I can see:
Unbind the key from ScintillaNET control (couldn't find out how to do this).
Find a way of identifying if the button is clicked or short-cut-keyed.
Make the appearance of a short-cut key without actually applying one.
Does anyone know how to do one of the above?
I would prefer not to override draw methods and the like.
EDIT:
I was a bit inaccurate about my question. It was actually a ToolStripMenuItem that I needed to check. Sadly it does not have a Focused property.
Found it!
I set the ShortcutKeyDisplayString in the form's constructor without actually setting a shortcut key.
public EditorForm()
{
....
undoToolStripMenuItem.ShortcutKeyDisplayString = "Ctrl+Z";
....
}

Refactoring Form to State Pattern?

I want to refactor some code.
Basically the code I want to refactor is a Form (using System.Windows.Forms;)
The way it is setup now, depending on which radio button you selected it shows a different layout for the window: different labels, buttons, etc. Not always a big difference, but different. This is a lot of conditional statement junk all over the place. I wanted instead to refactor it with the State pattern. There are three main states.
I'm not sure the best way to do this. Right now the IState interface has a DoAction() method which does some action particular to the unique State, and a DrawForm() method which re-draws the form based on the current State... However, to do the DrawForm(), the State classes need to be able to access the Form's member variables. That's what threw me for a loop. I didn't really want to expose them.
Is there a better way to do this?
You could make your state classes nested in your form. They will then be able to acces fields of form without having to expose them.
If your primary concern is keeping form stuff encapsulated, and you want to keep the state machine outside, I had a similar question a while back, you could check out the answer here - basically it entails creating a private inner 'action' class which DOES have access to form methods, then passing this to the state machine so that it can use the action class to invoke form methods indirectly.
I don't know if this helps, but why not have something like a strategy pattern for drawing the form?
So something along the lines of
interface IDrawStrategy
{
void Draw(FormType form);
}
And then when you pick which state the form is in, you can assign the form's draw strategy. Yes, you will still need to give the draw method access to the Forms variables to allow it to position them, but it at least allows you to make it easier to add different looks based on the states.
In wanting to extract the "state" of the Form, you are describing a pattern better known as a "Presentation Model". You will find some good information and tips on how you generally want the Form and State to interact by reading this article by Martin Fowler. In your case, your Form is the "View" and your State is the Presentation Model. As always, Fowler does a great job answering this question and more.

Naming convention for controls [duplicate]

This question already has answers here:
textBoxEmployeeName vs employeeNameTextBox
(16 answers)
Closed 9 years ago.
Microsoft has naming guidelines on their website (here). Also I have the Framework Design Guidelines book.
What I could not find was a guideline about naming controls.
For example, a button, when dropped to a form, gets the typename + number, camel-cased as default name, such as "button1".
This is what I do: I delete the number and add a meaningful description after. For example "buttonDelete" or "buttonSave".
This way you do not have to maintain a big list of controls and their abbreviated names in a guideline somewhere.
Do you agree?
Here are some common ones:
frm Form
mnu Form menu
cmd Command button
chk Check button
opt Radio button
lbl Text label
txt Text edit box
pb Picture box
pic Picture
lst List box
cbo Combo box
tmr Timer
A longer list is at INFO: Object Hungarian Notation Naming Conventions for VB.
Caveat: The following is more directed at WinForm/WPF development. Patrick Peters rightly pointed out that there are bandwidth/performance issues at play when dealing with ASP.NET controls.
There isn't really a standard here, and I believe that this is because its one of the most arbitrary naming scenarios. In most cases, controls are private to the class, and only used lightly in event handlers.
Like other answerers, I too used to spend a non-trivial amount of time "fixing" control names. I would do things like "btnSave", "tbxName" (tbx for TextBox), etc. However, when explaining my scheme to someone else, I realized how arbitrary that was. Is "cbx" a ComboBox or a Checkbox?
This led me to re-examine what the designer does automatically and realize that I can clearly, consistently, and quickly name controls if I let the designer do the work. Its actually very similar to the suggestion of the question poster:
I replace the control number with the semantics of the control. Thus "button1" (the designer default) will be "buttonSave", and "listBox3" will become "listBoxWidgets". If there will only be one control of that type, I just remove the number: "errorProvider1" becomes "errorProvider".
So how is this better?
Meticulously "fixing" variable names is a waste of time if its an internal variable
Your naming scheme is likely to be ambiguous if it shortens a whole bunch of stuff (CheckBox versus ComboBox)
The designer gives a good, consistent starting point that is easy (and quick) to specialize
The length of the variable name is irrelevant when you use Intellisense
Control names group nicely and intuitively (in Intellisense) when prefaced by their type. When you have 15 TextBoxes on your Form, you just first remember you want a TextBox , type "textBox", and then pick the name from the list.
Anyone unfamiliar with your "scheme" can see it immediately and adopt it quicker than anything else.
It is VERY fast to provide useful control names...very little keyboard/mouse jockeying to do this...so high productivity with intuitive results. What is not to like?
PS. This is tending towards a Bikeshed question, but as I can paint a bikeshed, I went ahead and joined the discussion. ;)
I don't have a convention as such, but I do try to be very broad with the 'type' portion of the name. e.g. Button, Link Button, Image Button tend to be named 'somethingButton'. Combo boxes, radio button lists all end up as 'somethingSelector'. TextBoxes and Calendars are 'somethingInput'. That way I get a rough idea of what sort of control it is without the name being tied to the actual implementation. If I decide to replace an option button group with a dropdown then no need to rename!
I don't do WinForms for quite some time but what I did was two things.
uncheck 'generate member' (or however it is called) for things like labels, etc. Basically ensuring I keep as fields only things I need.
for those I need, set descriptive name. It if is necessary, append the name of the control (ie saveButton). If I don't feel like adding a control name adds any value I would not append the 'Button' and leave the name simply as 'save'.
Basically most of the time I would not create a member for save button at all. (If you have some save logic you still can have only OnSaving event handler subscribed to the button's Click event).
https://msdn.microsoft.com/en-us/library/ms233630(v=vs.110).aspx
Yes change those names
For me:
Button btnDescription
TextBox txtDescription
ComboBox cboDescription
etc...
GUI programming gets the short stick when it comes to conventions of all sorts. See my answer to another question for the guidelines I use for naming.
Yes, you need meaningful identifiers for any variable - control or not - the default names are only because your IDE knows nothing about your problem domain and so can't always 'guess' a better name.
I'm probably one of the last few people that still uses Hungarian notation. I know that argument that the IDE can tell you the variable type, but that doesn't help me when I'm coding in Notepad++ or looking at a printout.... anyway, I use the "btnSave", "cbOptions", "txtFirstName", "lblTitle", "ddlCardType", etc... I just like being able to glance at code and know what I'm looking at without looking for a declaration or hovering over a variable to get it's data type from the IDE.
I believe that current thinking frowns upon including the control type in the name. I'd be inclined to treat them as another other object I'm using and follow the same naming convention.
Certainly use meaningful naming, that goes without saying :) However, at the end of the day, if your naming convention still makes sense to you when you revisit your code months later then I'd probably stick with it.
Yes, I agree totally (but I rename it to ButtonDelete), so lowercase names are for variables in my case :)
Personally, I think as long as you are consistent, you won't run into problems even if someone else is reading your code.
I'm not sure, but I think that control naming in Windows Forms is one of the only places I can see a use for Hungarian notation. So I think you're good.
This is what we are using
In short, we prefix the controls with an abbreviation of the control. ie
Buttons = btnDelete, btnSubmit, btnReturn
Textboxes = txtUsername, txtPassword etc
that way, by typing the abbreviation you get all the similar controls by the time you finish typing the abbreviation ie type btn and intellisense will list all the buttons you have added so far.

Categories