Multiple checkbox selections to display in textbox - c#

I'm new to this, please bare with...
I have 4 checkboxes, each displaying a $ amount depending on the selection.
I have it working so that if 1 checkbox is selected, textbox shows $1.00 or $20.00.
But, I'm having trouble with if 2 checkboxes are selected it would be $21.00 or 3 checkboxes or all 4.
I have this to show one checkbox selection.
if (checkBox247Access.Checked)
{
textBoxExtras.Text = "$1.00";
}

something like this should work, but as in comment above you might want to use particular container to iterate through i.e. iterate through groupbox instead of entire form just incase you have checkboxes in other container/groupboxes
foreach (Control ctrl in form1.Controls)
{
if (ctrl is CheckBox)
{
//do the logic of if checkbox is checked
}
}

One thing you can do, is handle the CheckedChanged event for all 4 checkboxes. You can even use the same eventhandler for all 4.
Then, in the handler, add up alle the selected extra options, and add them to a variable. After figuring out the total amount, update the textbox.
Here's an example:
private void checkBox_CheckedChanged(object sender, EventArgs e)
{
int amount = 0;
if (checkBox247Access.Checked)
{
amount += 20;
}
if (checkBoxFreeCoffee.Checked)
{
amount += 1;
}
if (checkBoxExtraThing.Checked)
{
amount += 3;
}
if (checkBoxBonusThing.Checked)
{
amount += 11;
}
textBoxExtras.Text = "$" + amount.ToString("n2");
}

Related

Disable multiple controls based upon Combo Box value

I have tried a number of iterations to get this to work, and although I am close, I cannot seem to solve this.
private void cbxMealsNum_SelectedIndexChanged(object sender, EventArgs e)
{
int count = 0;
int cbxCurr = cbxMealsNum.SelectedIndex+1;
foreach (Control control in foodMeals.Controls.OfType<ComboBox>().Where(x => x.Name.Contains("MealsNo" + cbxMealsNum.Text)))
{
TextBox textBox = control as TextBox;
if (count < cbxCurr)
{
control.Enabled = true;
}
else
{
control.Enabled = false;
}
count++;
}
}
The above code allows me to Enable the correct combo box but none of the combo boxes before it. As such, if I select '6' in cbxMealsNum, meal 6 is enabled, but not the 5 preceding it.
Thus, I am asking how I would change the index for cbxMealsNum to, say, 4, and have only cbxMealsNo1 through to 4 enabled. If I then change cbxMealsNum to 3, cbxMealsNo4 should be disabled. If I change cbxMealsNum to 5, cbxMealsNo4 should be enabled once more, as should cbxMealsNo5.
I have tried a number of iterations of this code, including the following answer here as seen in the above sample, but to no avail. I am new to C# but I have been looking for every possible solution I can. I do not know if my search terms are malformed.
Please note, I have used the Where method as I intend to add textboxes and other controls contain the same naming convention (thus; cbxMealsNo1, txtMealsNo1, lblMealsNo1, and so on)
I am assuming you want all the combos enabled up to the selected number in the “number of meals” combo box. If this is the case then the code below may help.
First, it may be easier to put all the combo boxes into a collection since you will be needing them each time the “number of meals” combo box changes. It seems unnecessary to “re-collect” them each time. In the example below I created a simple array of six (6) combo boxes. We can then use that array to loop through all the combo boxes and enable the proper combo boxes.
ComboBox[] combos = new ComboBox[6];
public Form1() {
InitializeComponent();
combos[0] = cbxMealsNo1;
combos[1] = cbxMealsNo2;
combos[2] = cbxMealsNo3;
combos[3] = cbxMealsNo4;
combos[4] = cbxMealsNo5;
combos[5] = cbxMealsNo6;
}
Then in the “number of meals” selection changed event, a simple loop to enable all the combo boxes that are less than the selected number of meals. Something like….
private void cbxMealsNum_SelectedIndexChanged(object sender, EventArgs e) {
int cbxCurr = cbxMealsNum.SelectedIndex;
for (int i = 0; i < combos.Length; i++) {
if (i <= cbxCurr) {
combos[i].Enabled = true;
}
else {
combos[i].Enabled = false;
}
}
}

Counting rows in datagridview using c#

I used following code to count datagrid rows, but it works on button only. I want the total number of rows in a textbox, but it doesn't increment itself as the number of rows increase.
int numRows = dataGridView1.Rows.Count;
txtTotalItem.Text = numRows.ToString();
When you assign the number, the textbox will display only that number, it will not update.
You can use an event and assign the new number to the textbox.
dataGridView1.RowsAdded+=(s,a)=>OnRowNumberChanged;
private void OnRowNumberChanged()
{
txtTotalItem.Text = dataGridView1.Rows.Count.ToString();
}
Following Equalsk's answer, you need to have the event for removed rows as well. You can subscribe to both events with the same function since you need to just check the number.
dataGridView1.RowsRemoved+=(s,a)=>OnRowNumberChanged();
If I've understood your question correctly you want the TextBox value to change automatically when rows are added or removed because at the moment you have to press a button to refresh. Am I right?
If so just subscribe to the .RowsAdded and .RowsRemoved events and update the TextBox from there.
dataGridView1.RowsAdded += RowsAdded;
dataGridView1.RowsRemoved += RowsRemoved;
private void RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
txtTotalItem.Text = dataGridView1.Rows.Count.ToString();
}
private void RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
{
txtTotalItem.Text = dataGridView1.Rows.Count.ToString();
}
the datagridview will count the last empty row so make sure to
look for AllowUserToAddRows property of datagridview and set it to False.
Or add this to your code, in my case i used a label and i named it labelTotalResult, do this if you want to keep the property as true
labelTotalResult.Text = (dataGridView1.RowCount - 1).ToString();

Fill Textbox with Data from RadGrid

When I click on an item I would like to fill my TextBox with numbers from a column from Grid2 after Grid1 is clicked. Right now if I click on an item in Grid1 it will then run a procedure that will fill Grid2 with data. Here is an example of the current functionality with picture attached, I click an item from Grid1 and it has 3 results, my textbox will still display as an empty textbox. Then I click another item in Grid1 and now my textbox will display the 3 results from the previously clicked item. How can I display the correct numbers in my textbox after an item is selected in Grid1.
I have tried a few different methods including:
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
divDetails.Visible = true;
RadTextBox1.Text = "";
for (int i = 0; i < Grid_Product_List_Details.Items.Count; i++)
{
RadTextBox1.Text += Grid_Product_List_Details.Items[i].GetDataKeyValue("number").ToString() + "\n";
}
}
and:
protected void Grid_Product_List_Details_PreRender(object sender, EventArgs e)
{
RadGrid grid = (RadGrid)sender;
if (grid.Items.Count > 0)
{
RadTextBox1.Text = "";
}
for (int i = 0; i < grid.Items.Count; i++)
{
RadTextBox1.Text += grid.Items[i].GetDataKeyValue("number").ToString() + "\n";
}
RadTextBox1.DataBind();
}
and this:
protected void Grid_Product_List_Header_SelectedIndexChanged(object sender, EventArgs e)
{
RadTextBox1.Text = "";
for (int i = 0; i < Grid_Product_List_Details.Items.Count; i++)
{
RadTextBox1.Text += Grid_Product_List_Details.Items[i].GetDataKeyValue("number").ToString() + "\n";
}
}
But those aren't working. Any suggestions?
Try to change your code a little bit.
RadTextBox1.Text = "";
foreach (GridDataItem dataItem in Grid_Product_List_Details.Items)
{
RadTextBox1.Text += dataItem.GetDataKeyValue("number").ToString() + "\n";
}
RadTextBox1.DataBind();
This should work though I suspect your earlier code should work too.
I ended up creating a procedure which fills the textbox after an item is clicked so the most recent data appears.
Try the ItemDataBound event of the second grid. You will have access to all of its data so you can put that in the RadTextBox. I suspect you provide a data source to the second grid in the SelectedIndexChanged of the first, so its Rebind() method should be called and then you will get the ItemDataBound fired for each of its rows.
Also, if you are using AJAX - disable it. It is possible that something does not get properly updated with the partial rendering. If things work fine with full postbacks, examine the responses and see why the textbox is not included in the first request so you can know how to tweak your AJAX setup.

CheckedListBox Only One Checked But Keep Last

I am having some difficulty getting a CheckedListBox to behave the way I want it to. What I am trying to accomplish is getting a CheckedListBox with the first box checked on PageLoad. I want only one checkbox checked at any given time but I also don't want the user to uncheck the last checked box. I can do one or the other but I can't seem to do both.
Here is some code snippets that I have used to accomplish the task of having only one checkbox checked. The problem with these are the last selection can be unchecked where there are no checkboxes checked.
1st Snippet:
if(e.NewValue == CheckState.Checked)
{
// Uncheck the other items
for (int i = 0; i < defCheckedListBox.Items.Count; i++)
{
if (e.Index != i)
{
this.defCheckedListBox.SetItemChecked(i, false);
}
}
}
2nd Snippet
// Ensure that we are checking an item
if (e.NewValue != CheckState.Checked)
{
return;
}
// Get the items that are selected
CheckedListBox.CheckedIndexCollection selectedItems = this.defCheckedListBox.CheckedIndices;
// Check that we have at least 1 item selected
if (selectedItems.Count > 0)
{
// Uncheck the other item
this.defCheckedListBox.SetItemChecked(selectedItems[0], false);
}
Here is what I have used to prevent the last checked box to be "unchecked"
if (laborLevelDefCheckedListBox.CheckedItems.Count == 1)
{
if (e.CurrentValue == CheckState.Checked)
{
e.NewValue = CheckState.Checked;
}
}
I know this has got to be simple but I think because I've had a long week and I have looked at this too long it is just not coming to me. Any help with this is super appreciated! If I solve this over the weekend I will be sure to post my solution. BTW Happy Holidays to those here in the States :)
Chris makes a good point in the comments that this feels like you are re-inventing radio buttons but you are almost there with the code you have posted if you really want it to work with a CheckedListBox. I have adapted the code from your 1st Snippet which I think does the trick:
//remove the event handler so when we change the state of other items the event
//isn't fired again.
defCheckedListBox.ItemCheck -= defCheckedListBox_ItemCheck;
if (e.NewValue == CheckState.Checked)
{
// Uncheck the other items
for (int i = 0; i < defCheckedListBox.Items.Count; i++)
{
if (e.Index != i)
{
this.defCheckedListBox.SetItemChecked(i, false);
}
}
}
else
{
//the state was not checked.
//as only one item can ever be Checked inside the event
//handler the state of not checked is invalid for us; set the state back to Checked.
e.NewValue = CheckState.Checked;
}
//re-add the event handler
defCheckedListBox.ItemCheck += defCheckedListBox_ItemCheck;
Essentially the only new parts are the else where we reset the state if the state was not Checked and the removing and re-adding of the event to prevent it firing again when we manually set the state of other items (this could be handled with a global bool if you prefer).
// Use CheckBoxList Event
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
// Stops DeInitialize Event
checkedListBox1.ItemCheck -= checkedListBox1_ItemCheck;
// Get the new value old value my be in Indeterminate State
checkedListBox1.SetItemCheckState(e.Index, e.NewValue);
// Start ReInitialize Event
checkedListBox1.ItemCheck += checkedListBox1_ItemCheck;
}

In WPF, what is the best way to make buttons that insert special characters into multiple TextBoxes?

If I have multiple TextBoxes and other text insertion controls and I want to create some buttons that insert special characters into whichever TextBox is in focus, what is the best control for this and what properties should be set?
Requirements for the buttons:
Buttons do not steal focus when clicked.
Buttons can insert text (e.g. special characters) into any control that accepts keyboard input.
The cursor should move as if the user had entered the text on the keyboard.
If #2 is not possible, it will suffice to limit the controls to only TextBoxes.
NOTE: I do not want to make the buttons unfocusable, only such that they do not steal focus when clicked.
I'm not aware of any button that is not stealing focus when it is clicked, but in button click event handle you can return focus to previous owner. If I had to implement this I'd create an behavior that is attached to parent panel of all special textboxes and all buttons that are to insert some text.
<StackPanel>
<i:Interaction.Behaviors>
<local:TextBoxStateTracker/>
</i:Interaction.Behaviors>
<TextBox />
<Button Content="description" Tag="?" />
</StackPanel>
For sample simplicity I've put text that is to be inserted to textbox in Tag property.
public class TextBoxStateTracker : Behavior<Panel>
{
private TextBox _previouslySelectedElement;
private int _selectionStart;
private int _selectionLength;
protected override void OnAttached()
{
//after control and all its children are created find textboxes and buttons
AssociatedObject.Initialized += (x, y) =>
{
var textBoxElements = FindChildren<TextBox>(AssociatedObject);
foreach (var item in textBoxElements)
{
item.LostFocus += new RoutedEventHandler(item_LostFocus);
}
var buttons = FindChildren<Button>(AssociatedObject);
foreach (var item in buttons)
{
item.Click += new RoutedEventHandler(item_Click);
}
};
}
private void item_Click(object sender, RoutedEventArgs e)
{
if (_previouslySelectedElement == null) return;
//simply replace selected text in previously focused textbox with whatever is in tag property
var button = (Button)sender;
var textToInsert = (string)button.Tag;
_previouslySelectedElement.Text = _previouslySelectedElement.Text.Substring(0, _selectionStart)
+ textToInsert +
_previouslySelectedElement.Text.Substring(_selectionStart + _selectionLength);
_previouslySelectedElement.Focus();
_previouslySelectedElement.SelectionStart = _selectionStart + textToInsert.Length;
}
private void item_LostFocus(object sender, RoutedEventArgs e)
{
//this method is fired when textboxes loose their focus note that this
//might not be fired by button click
_previouslySelectedElement = (TextBox)sender;
_selectionStart = _previouslySelectedElement.SelectionStart;
_selectionLength = _previouslySelectedElement.SelectionLength;
}
public List<TChild> FindChildren<TChild>(DependencyObject d)
where TChild : DependencyObject
{
List<TChild> children = new List<TChild>();
int childCount = VisualTreeHelper.GetChildrenCount(d);
for (int i = 0; i < childCount; i++)
{
DependencyObject o = VisualTreeHelper.GetChild(d, i);
if (o is TChild)
children.Add(o as TChild);
foreach (TChild c in FindChildren<TChild>(o))
children.Add(c);
}
return children;
}
}
This does more or less what you described but it is far from perfect I think it is enough to get you started.
You need to do override the template of a Label and a TextBox.
requirements 1 and 2 - can be done inside the template for the Label which will act as a button.
requirement 3 - can be done inside the the template for the Textbox.
It's not easy...
you might need to learn alot of WPF styling, XAML and overriding the Control Template. maybe even creating a custom control.

Categories