Populate ShortcutKeys in a loop - c#

I have a ToolStripMenuItem that serves as a drop down menu attached to the MenuStrip of my Form. The contents of this menu change depending on the status of the rest of the form and are populated in a loop.
The problem is that now I would like to add the functionality that the items in this menu have a keyboard shortcut based on their position in the list. The first item in the list should be Ctrl+1, the second Ctrl+2, etc.
Since ShortcutKeys is set using the Keys enum I do not know how I could map an incrementing value to the proper values in the enum. I had hoped something like this would work, but it did not:
newToolStripMenuItem.ShortcutKeys = Keys.Control | (Keys.D0 + menuItemNumber++);
Edit
There may be something else going on. According to this asker my initial solution should have worked, and the solution proposed by Migol produces the same result. The value in ShortcutKeys is shown to be some odd combination of characters with no apparent pattern.

You can use Enum.Parse method like this:
string enumName = "D" + menuItemNumber++;
newToolStripMenuItem.ShortcutKeys = Keys.Control | (Keys)Enum.Parse(typeof(Keys), enumName);
Enum.Parse documentation

This is embarrassing, but the problem completely unrelated to anything mentioned in this post. It was a stupid mistake made by my own bad programming habits in combination with a typo.
In my original ask I changed the name of my local variable from processorToolStripMenuItem to newToolStripMenuItem since this made more sense out of the context of the application. The item I was adding it to was a field named procesorToolStripMenuItem which as you can see is missing an 's'.
For the line of code setting the keyboard shortcut I made the same typo and was thus setting the keyboard shortcut of the wrong thing. They should never have been named something so similar to one another in the first place.

Related

Best way to pass values in C#/XAML

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.

Getting the computer to select the appropriate Category and Label

So I have the makings of a top trump game where the main form is populated with 10 labels, 5 on the player side and 5 on the computer side.
I need guidance on the best way to get the highlighted label/category on the computer side.
So what happens is that you press the New Game button
Player selects a category (Say Intelligence). (PlayerlblIntelligence)
The Player selected label is highlighted
Compare button is pressed.
WHat I want to happen after the Compare button is pressed is that:
Program gets selected player label and stores that value
Computer then looks up the same category on it's current card
Highlights it and then runs a comparison method.
What is the best way to get the equivalent category and label for the computer (so that it highlights and gets the equivalent category/value.
The way I have it get the value of the selected label is to regex the label text so that it pulls out the number and use that for comparison. However, the wife states that seems wrong and that the program should use some other method instead of the label text (as it shouldn't know anything about that).
I'm just got to the stage where I can't think of a better way to do it.
Link to Gist where the TopTrumpClass and Form classes are
GistHub Source Code
Edit: Thinking out aloud,
1) I get it to read the value of the selected label (so if Intelligence is 85, it gets the int value of 85)
2) Compare that value to the players cardsinhand[0] properties and match it
3) Look at the Computer cardsinhand[0] and look up the same property.
4) Obtain the value and then run a comparison and highlight label method (although how I get it to highlight the right label might be tricky).
Would the steps 1-4 work. If so, what's the best way to match the values to the card's properties. Would I be looking at using Attribute.GetCustomAttribute for example (How to get a property value based on the name)
Started as a comment, but kept growing :
This is a wee broad, don't you think ? It's not about a specific problem, and nothing is "broken", so it might not be a good fit for this site.
Also, going through 500+ lines of your code isn't gonna happen for me (think about, what's in it for the person taking his time to look at your code ...). Maybe codereview # stackexchange would be a better fit.
Having said that, your wife is right, reading the label and regexing the result isn't right.
You should probably have the values somewhere (since it's your program). Have you considered maybe a dictionary so you can easily match a string to a value?

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";
....
}

Disabling item in a ComboBox C#

I have found what seems to be an easy solution to disable certain items in a ComboBox in here. It states:
You can disable an item in a list box or combo box by adding a single
backslash to the beginning of the expression.
However if I write
testBox.Items.Add("\Test item");
or
testBox.Items.Add(\"Test item");
it gives a syntax error in VS2010. Maybe this function has been disabled in later than 2005 versions?
If I put an item through a VS2010 designer like this
\Test item
or I write
testBox.Items.Add("\\Test item");
then it appears with a backslash and not is disabled.
Thus my question is: is this method somehow available and I just fail to understand how to use it or I do have to create a custom ComboBox to achieve my goal (in title)?
sadly is it not possible for the combobox control.
I would recommend to just remove the item from the combobox list instead of trying to disable it.
with one of those 3 ways:
// To remove item with index 0:
comboBox1.Items.RemoveAt(0);
// To remove currently selected item:
comboBox1.Items.Remove(comboBox1.SelectedItem);
// To remove "Tokyo" item:
comboBox1.Items.Remove("Tokyo");
If you absolutely need to disable items, you will need to create a custom combobox.
UPDATE 1: This does NOT work, but I'm leaving it as is so the comments below make sense.
UPDATE 2: To answer your question... After a bit of googling around I believe your only option to achieve this with WinForms is to create your own control as you suggested.
I suspect the rules for working with items that begin with multiple backslashes would apply to escape sequences too. How about:
testBox.Items.Add("\]Test Item");
I'm not able to test it out, but it looks like it should work.
In general: You need to escape the backslash by writing \\. Otherwise the compiler tries to interprete \T as an escape sequence (which does not exist). I guess the designer does this for you already, but you can always take a look in the generated source code ;)
About disabling combobox items: The documentation you linked seems to apply for ListBoxes, not ComboBoxes. Furthermore, it refers to VisualFox Pro, not Windows.Forms. So I guess this won't work ;)
According to this discussion, you will need to subclass the control and overrride its paint handlers.
But before doing that, I would simply remove (or not even add) those items you wish to disable.

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