Attempting to condense my c# - c#

I am attempting to condense my c# code because it's way too long and I feel I could use a foreach loop for my code. And you will have to excuse me if my terminology/vocabulary is incorrect, I am a Jr. programmer and still picking up the pieces.
A snippet of my code:
if (sender == LinkButtonA)
{
Session["LastNameFilter"] = "A";
}
if (sender == LinkButtonB)
{
Session["LastNameFilter"] = "B";
}
if (sender == LinkButtonC)
{
Session["LastNameFilter"] = "C";
}
if (sender == LinkButtonD)
{
Session["LastNameFilter"] = "D";
}
etc.....
Basically it is changing the filter so that I can display my "patients" in a RadGrid and filter them by their last name. But as you can see, I have to have 26 if statements just to make this work. Is their a cleaner way to do this?

You could have a dictionary mapping the buttons to the filters:
static Dictionary<Button, string> mapping = new Dictionary<Button, string>() {
{ LinkButtonA, "A" },
{ LinkButtonB, "B" },
{ LinkButtonC, "C" },
{ LinkButtonD, "D" },
};
...
Session["LastNameFilter"] = mapping[sender];

Register your buttons in a Dictionary<Button,string> :
Dictionary<Button,string> lastNameFilterByButton = new Dictionary<Button,string>()`
mapping.Add(LinkButtonA, "A");
mapping.Add(LinkButtonB, "B");
mapping.Add(LinkButtonC, "C");
mapping.Add(LinkButtonD, "D");
// ...
Session["LastNameFilter"] = lastNameFilterByButton[sender]

Set the Tag property on your buttons to the appropriate string, then set the session value to the tag:
// in the designer file
LinkButtonA.Tag = "A";
LinkButtonB.Tag = "B";
// etc.
// in the event
var btn = sender as LinkButton;
if (btn != null)
Session["LastNameFilter"] = (string)btn.Tag;
Edit: Tag is found on WinForms controls, ASP controls don't have a direct equivalent. You could probably safely use the CommandArgument property for this, though, if you're not using it for anything else (as pointed out by Jason Nesbitt).
You could also use the name of the button (Session["LastNameFilter"] = btn.Name.Substring(btn.Name.Length-1, 1);). This saves you the trouble of messing with the Tags, but means everything breaks if you change your naming convention.

What about something like
// Is sender of type Control?
Dictionary<Control, string> lookupBasedOnButton = new Dictionary<Control, string>()
{
{ LinkButtonA, "A" },
// etc
};
Session["LastNameFilter"] = lookupBasedOnButton(sender);
Depending on your needs, you might need to add error handling (e.g. check whether the item is in the dictionary, rather than throwing if it is not).

Store and fetch the value from the CommandArgument property of the LinkButton.
<asp:LinkButton runat="server" ID="LinkButtonA" CommandArgument="A" OnClick="LinkButtonA_OnClick"></asp:LinkButton>
protected void lb LinkButtonA_OnClick(object sender, EventArgs e)
{
var lb = (LinkButton) sender;
Session["LastNameFilter"] = lb.CommandArgument;
}

If you are able to add the filter value as a Command Argument to the Button then you only would need to do this (Applies to web forms LinkButton):
public void LinkButtonClicked(object sender, EventArgs e){
var linkButton = (LinkButton)sender;
Session["LastNameFilter"] = linkButton.CommandArgument;
}

Related

howto pass dictionary key in a form event C#?

Here is the code that I am running:
private Dictionary<string, List<GuiEvent>> m_events = new Dictionary<string, List<GuiEvent>>();
private void OnRadioBtnCheckedChange(object sender, EventArgs e, string formhandle)
{
RadioButton control = (RadioButton)sender;
GuiEvent evnt = new GuiEvent
{
id = GuiEventType.RadioButtonChange,
ElementName = control.Name,
sparam = control.Text,
lparam = control.Checked ? 1 : 0
};
m_events[formhandle].Add(evnt);
}
Getting the error:
Severity Code Description Project File Line Suppression State
Error CS0123 No overload for 'OnRadioBtnCheckedChange' matches delegate 'EventHandler' MtGuiController C:\Users\AIMS-RESEARCH\Desktop\MtGuiController\MtGuiController\Controller.cs 258 Active
Previously when the m_event was declared like this:
private List<GuiEvent> m_events = null;
And the function:
private void OnRadioBtnCheckedChange(object sender, EventArgs e)
{
RadioButton control = (RadioButton)sender;
GuiEvent evnt = new GuiEvent
{
id = GuiEventType.RadioButtonChange,
ElementName = control.Name,
sparam = control.Text,
lparam = control.Checked ? 1 : 0
};
m_events.Add(evnt);
}
Everything was working fine.
I am not able to understand what I can do in this situation. I cannot declare string formhandle as global as it is changing every time. So please take a note of it. It is C# DLL function.
Can anybody tell me solution that will help?
If you want to use some additional information in your event handler, you cannot pass it as an additional parameter to event handling function. You cannot also change type of event handler parameters - it should just accept two arguments - sender and EventArgs.
You have three options here. First - store data in sender and then access that data in event handler. Simplest way is using radio button's tag. Control.Tag is inherited from base Control class and you can use it to store some data when you create control. I.e. assign appropriate formhandle to every radio button Tag (you can even do that manually via designer)
radioButton1.Tag = "foo";
radioButton2.Tag = "bar";
and then retrieve it in event handler:
private void OnRadioBtnCheckedChange(object sender, EventArgs e)
{
RadioButton control = (RadioButton)sender;
GuiEvent evnt = new GuiEvent
{
id = GuiEventType.RadioButtonChange,
ElementName = control.Name,
sparam = control.Text,
lparam = control.Checked ? 1 : 0
};
var formhandle = (string)control.Tag; // here you get "foo" or "bar"
m_events[formhandle].Add(evnt);
}
Second option - create your custom radio button control. But that's overkill here. Usually, you do that when you need a custom look & feel, not just to pass data.
Third option - lookup data you want using the data you have (e.g. control name). This option makes sense when data you need is not available at the time of control creation or if it changes over time.

Set and get checked boxes in MultiSelectListPreference

I'm defining the MultiSelectListPreference in my axml file like this:
<MultiSelectListPreference
android:title="Title"
android:summary="Sum"
android:key="dutyMarks"
android:entries="#array/array_marks"
android:entryValues="#array/array_marksValues">
</MultiSelectListPreference>
How can check / read the checked boxes in code?
I tried to get the checked values via the PreferenceChange event:
The checked values appear there, but I have no idea how to get them...
This was also my first thought, but e.NewValue doesn't contain a public definition for 'GetEnumerator'.
We can simply cast e.NewValue from object to IEnumerable in our code, for example:
private void PreferenceChange(object sender, Preference.PreferenceChangeEventArgs e)
{
var selections = e.NewValue as IEnumerable;
if (selections != null)
{
foreach (var selection in selections)
{
Console.WriteLine(selection);
}
}
}
since e.NewValue is a HashSet, you should be able to iterate through it
foreach (string x in e.NewValue) {
// do whatever you need to do with each value x here
}
If someone stumbles across this question, here is how i solved it:
Read (the async part is pretty ugly, but I don't know how to add a 'preferenceChangeD' event)
private async void preferenceChange(object sender, Preference.PreferenceChangeEventArgs e)
{
await System.Threading.Tasks.Task.Delay(100);
List<string> sList = new List<string>();
ICollection<string> selectedValues = mslp_dutyMarks.Values;
foreach(string x in selectedValues)
sList.Add(x);
}
Write
mslp_dutyMarks.Values = new List<string> { "A", "B", "C" };

Retrieve TextBox By Name

In my project i know the names of TextBoxes which are dynamically generated is there any solution to retrieve this TextBox text from other methods.In other sense i want to get TextBox by name and want to use in other part of code.
I have TextBox allocated like this...
private void Met(string rowNo)
{
TextBox t2 = new TextBox();
t2.Name = "itemAmt" + rowNo;
PurchaseItemEntryDyPanel.Controls.Add(t2);
}
Is there any way other than using name? Any Solution?
I personaly use name when I want to read posted data from a form.
And I would use Id when controls are supposed to be unique. So the code is a little different:
var t2 = new TextBox();
t2.ID = "itemAmt" + rowNo;
//since you mention in the comments, add it to the panel
yourPanel.Controls.Add(t2);
Then to get the textBox value
var controlId = "itemAmt" + rowNo;
var t2 = ((TextBox)(yourPanel.FindControl(controlId)));
if(t2 != null)
{
//do someting
//t2.Text = "something";
//t2.Enabled = true;
}
If you are not willing to make that change, go over the solution posted earlier.
You can get your TextBox from Controls collection of Form by it's name like this:
var myTextBox = this.Controls[textBoxName];
You don't show too much of your code, but I assume you're adding it to the collection of controls on your form. Otherwise, the TextBox you create in Met goes out of scope when your method ends, just like any other local variable.
private void Met(string rowNo)
{
TextBox t2 = new TextBox();
t2.Name = "itemAmt" + rowNo;
this.Controls.Add(t2); // need to add the TextBox to your form's controls
}
Then you can use Selman22's solution or, if the control might be added to a GroupBox or Panel, you'll want to search all child controls too:
var myControl = this.Controls.Find("itemAmt4", true);
if (myControl != null)
myControl.Enabled = true;
Use this in your Class:
foreach (Control tempCtrl in this.Controls)
{
// Determine he control is textBox1,
if (tempCtrl.Name == "itemAmt" + rowNo)
{
this.Controls.Remove(tempCtrl);
}
}

c# How do i change the color of a specific textbox if it is empty?

I am trying to change the color of an empty textbox, I have more than one textbox on this form and i wish to highlight the empty one when a user clicks submit. I have written the loop below which is in my btnSubmit function after checking if all the textbox have a value. Can anyone help in completing this loop for me??
foreach (Control txtbxs in this.Controls)
{
if (txtbxs is TextBox)
{
var TBox = (TextBox)txtbxs;
if (TBox.Text == string.Empty)
{
TBox.ForeColor = Color.Red;
}
}
}
lblTopError.Text = "Please fill in the missing billing information";
pnlTopError.Visible = true;
When your string is empty, changing the ForeColor will do nothing since you don't have Text to display in red. Consider using BackColor and remember to have an event when text is entered to switch it back to the appropriate BackColor.
If this is what you are trying to do, have you considered using the error provider? this would help you to signal the user and prompt them to put in the information.
errorProvider= new System.Windows.Forms.ErrorProvider();
errorProvider.BlinkRate = 1000;
errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.AlwaysBlink;
private void TextValidated(object sender, System.EventArgs e)
{
var txtbox = Sender as TextBox;
if(IsTextValid(txt))
{
// Clear the error, if any, in the error provider.
errorProvider.SetError(txtbox, String.Empty);
}
else
{
// Set the error if the name is not valid.
errorProvider.SetError(txtbox, "Please fill in the missing billing information.");
}
}
You can apply any CSS you want like this:
TBox.Attributes.Add("style", "color: red; border: solid 1px #FC3000")
I would use this instead of:
TBox.ForeColor = Color.Red;
Well since there aren't much textboxes in this form, i went the easy route and it worked, code bellow:
List<TextBox> boxes = new List<TextBox>();
if (string.IsNullOrWhiteSpace(txtFname.Text))
{
//highlightTextBox= txtFname;
boxes.Add(txtFname);
}
if (string.IsNullOrWhiteSpace(txtLname.Text))
{
//highlightTextBox = txtLname;
boxes.Add(txtLname);
}
if (string.IsNullOrWhiteSpace(txtAddOne.Text))
{
//highlightTextBox = txtAddOne;
boxes.Add(txtAddOne);
}
if (string.IsNullOrWhiteSpace(txtTown.Text))
{
//highlightTextBox = txtTown;
boxes.Add(txtTown);
}
if (string.IsNullOrWhiteSpace(txtPostCode.Text))
{
//highlightTextBox = txtPostCode;
boxes.Add(txtPostCode);
}
foreach (var item in boxes)
{
if (string.IsNullOrWhiteSpace(item.Text))
{
item.BackColor = Color.Azure;
}
}
lblTopError.Text = "Please fill in the missing billing information highlighted below";
pnlTopError.Visible = true;

Why can't I leave a TextBox using tab?

I have this code:
public static void AddDefaultTextFromTag(params TextBox[] textBoxes)
{
foreach (TextBox oTextBox in textBoxes)
{
bool isPasswordChar = oTextBox.UseSystemPasswordChar;
oTextBox.Enter += (sndr, evnt) =>
{
if (((TextBox)sndr).Text == ((TextBox)sndr).Tag.ToString())
{
((TextBox)sndr).Text = "";
((TextBox)sndr).UseSystemPasswordChar = isPasswordChar;
((TextBox)sndr).ForeColor = SystemColors.WindowText;
}
};
oTextBox.Leave += (sndr, evnt) =>
{
if (((TextBox)sndr).Text.Trim().Count() == 0)
{
((TextBox)sndr).UseSystemPasswordChar = false;
((TextBox)sndr).CharacterCasing = CharacterCasing.Normal;
((TextBox)sndr).Text = ((TextBox)sndr).Tag.ToString();
((TextBox)sndr).ForeColor = SystemColors.GrayText;
}
};
if (oTextBox.Text.Trim().Count() == 0)
{
oTextBox.UseSystemPasswordChar = false;
oTextBox.CharacterCasing = CharacterCasing.Normal;
oTextBox.Text = oTextBox.Tag.ToString();
oTextBox.ForeColor = SystemColors.GrayText;
}
}
}
But when the TextBox.UseSystemPasswordChar I input in this method's parameter is true and it's TextBox.Text property is empty, the TextBox can't leave using a Tab button on the keyboard, only a MouseClick can be used to lose the focus of that TextBox.
Why is this happening?
My code is in C#, framework 4, build in VS2010 Pro, project is in WinForms.
I use a TextBox from the VS ToolBox.
Please help. Thanks in advance.
The reason you can't leave the textbox is because you are changing the CharacterCasing property in the textbox.
Not sure why it works like this, but it has happened to me before, what I ended up doing was capture the keypress event, and if it was a letter I'd switch it to it's uppercase value. It's not optimal, but it works
I did something similar to this (writing it from the top of my head, but it should work):
void YourTextbox_KeyPress(object sender, KeyPressEventArgs e)
{
if (char.IsLetter(e.KeyChar))
{
if (this.CharacterCasing == CharacterCasing.Upper && char.IsLower(e.KeyChar))
{
this.Text = this.Text.Insert(this.SelectionStart, char.ToUpper(e.KeyChar) + string.Empty);
this.SelectionStart++;
e.Handled = true;
}
else if (this.CharacterCasing == System.Windows.Forms.CharacterCasing.Lower && char.IsUpper(e.KeyChar))
{
this.Text = this.Text.Insert(this.SelectionStart, char.ToLower(e.KeyChar) + string.Empty);
this.SelectionStart++;
e.Handled = true;
}
}
}
You also should use the new keyword to "override" (I know that's not the right term here) the Character casing, so it doesn't do it's own thing
public new CharacterCasing CharacterCasing { get; set; }
The code basically checks if the pressed key is a letter, then, if it's marked as Upper, and the char is lower, replaces it with it's upper version (in the position of the cursor) then moves the cursor to the next part, and Viceversa (toLower)
NOTE:
This code will have may (should) have some trouble if the user has more than one character selected (SelectionLenght > 0), if you want to keep the normal Textbox functionality, you should delete all the selected characters
So I set up a WinForms app, drew two textboxes, set one to UseSystemPasswordChar=true then set it up like so:
private void Form1_Load(object sender, EventArgs e)
{
textBox2.Tag = "test2";
textBox1.Tag = "test1";
TextBox[] tb = { textBox1, textBox2 };
AddDefaultTextFromTag(tb);
}
Your function works fine and I have no problems tabbing through the controls on the form no matter what the textboxes contain. (added a button also that does nothing for tabbing test) so... no repro unless my test setup is not valid
What I found in the answer of this post was the solution for me. Instead of setting UseSystemPasswordChar to true and then to false, you can set PasswordChar to '●' and then to '\0' to have normal text. You should not set the UseSystemPasswordChar because it has precedence over PasswordChar.

Categories

Resources