Check more than one checkbox upon clicking a button c# - c#

I have for example:
Checkbox1.IsChecked = true;
Checkbox2.IsChecked = true;
Checkbox3.IsChecked = true;
I have this 32 times. Is there a way to have concat string? For example:
i = 1
while i < 32:
("Checkbox"+ (i)).IsChecked = true;
i++
Thanks

While you cannot do exactly what you intend, you can check or uncheck all checkboxes that are in a given container. For example, let's say you have a Panel that contains a number of checkboxes, called pnlChecks. You could do something like
foreach (var chkBox in pnlChecks.Controls.OfType<CheckBox>())
{
chkBox.IsChecked = true;
}

There are multiple methods to achieve this.
Add all of them to a generic List<> and iterate through them like the for you mentioned.
Use reflection and get the checkbox controls and set their value.
Sample WinForms Code
private List<CheckBox> checkboxes = new List<CheckBox>();
public Form1()
{
InitializeComponent();
FillCheckboxes();
}
private void CheckAll()
{
foreach (var chk in checkboxes)
{
chk.Checked = true;
}
}
private void FillCheckboxes()
{
foreach (Control c in this.Controls)
{
if (c is CheckBox)
{
checkboxes.Add(c as CheckBox);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
CheckAll();
}
Sample WPF Code
private List<CheckBox> checkboxes = new List<CheckBox>();
public Window1()
{
InitializeComponent();
checkboxes = FindVisualChildren<CheckBox>(main).ToList();
CheckAll();
}
private void CheckAll()
{
foreach (var chk in checkboxes)
{
chk.IsChecked = true;
}
}
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
Important Note
For WPF the suggested method is to use data binding instead of iterating through controls and manually checking/unchecking them. Just bind the IsChecked property to the desired value and change it. You can find more info regarding this on numerous articles on the Internet.

Related

How to link textbox and checkbox in C#

I started making a small program. The form contains checkbox1,2,3,4,.... and textbox1,2,3,4,5.... there is a code that looks at which of the checkboxes are marked. If there is any possibility to link textbox and checkbox. So that when a code marked with a checkbox is detected, the text is taken from the textbox given to it and transferred to the RichTextBox, using AppendText. Below is a sample code with a cyclic check of all the checkboxes on the form for the presence of checked on my form.
foreach (Control control in this.tabControl1.TabPages[0].Controls) //цикл по форме с вкладками
{
if (control as CheckBox != null) // проверка на пустое значение
{
if (control.Visible == true)// проверка на видимость
{
if ((control as CheckBox).Checked)// проверка на чек
{
}
else if ((control as CheckBox).Checked == false)
{
}
}
}
Use the following method to get CheckBox controls.
public static class ControlExtensions
{
public static IEnumerable<T> Descendants<T>(this Control control) where T : class
{
foreach (Control child in control.Controls)
{
if (child is T thisControl)
{
yield return (T)thisControl;
}
if (child.HasChildren)
{
foreach (T descendant in Descendants<T>(child))
{
yield return descendant;
}
}
}
}
}
In the form, use a Dictionary to pair CheckBox to TextBox. You can also check for visibility in the Where.
public partial class Form1 : Form
{
private readonly Dictionary<string, TextBox> _dictionary =
new Dictionary<string, TextBox>();
public Form1()
{
InitializeComponent();
_dictionary.Add("checkBox1", textBox1);
_dictionary.Add("checkBox2", textBox2);
_dictionary.Add("checkBox3", textBox3);
_dictionary.Add("checkBox4", textBox4);
_dictionary.Add("checkBox5", textBox5);
}
private void button2_Click(object sender, EventArgs e)
{
var list = tabControl1.Descendants<CheckBox>().ToList();
var #checked = list.Where(x => x.Checked).ToList();
var notChecked = list.Where(x => !x.Checked).ToList();
foreach (var checkBox in #checked)
{
TextBox textBox = _dictionary[checkBox.Name];
}
}
}
Create a UserControl with CheckBox and TextBox components. Create properties Checked and TextForAdd:
namespace Sort.UserPanel
{
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public bool Checked { get { return checkBox1.Checked; } }
public string TextForAdd { get { return textBox1.Text; } }
}
}
On the main form we add UserControl1 the necessary number of times.
private void testCheckBoxes(object obj)
{
if (obj is UserControl1 control)
{
string text = control.TextForAdd;
// .....
}
}
private void button1_Click(object sender, EventArgs e)
{
foreach (Control control in this.LeftPanel.Controls)
{
if (control as UserControl1 != null)
{
if (control.Visible == true )
{
testCheckBoxes(control);
}
}
}
}

Can't locate control from string

I have a custom extension method that (is supposed to) find a control via a string, and perform a click to that control. I've set up a break point and it nevers into the if (c is ToolStripMenuItem) Anyone have any idea where I'm going wrong? This is on WinForms.
private void PerformClickfromString()
{
string item = File.ReadAllText(#"C:\controltest.txt");
foreach (var c in this.Controls)
{
if (c is ToolStripMenuItem)
{
var x = (ToolStripMenuItem)c;
if (x.Name == item)
{
x.PerformClick();
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
PerformClickfromString();
}
Any help is appreciated.
To find all nested items you need a recursive search. Here is an example; it collects all items in a List<ToolStripMenuItem> and the checks for the searched name. I have added that string to the signature of your call..:
private void PerformClickfromString(string s)
{
foreach (var c in this.Controls)
{
List<ToolStripMenuItem> items = new List<ToolStripMenuItem>();
if (c is MenuStrip)
{
foreach (ToolStripMenuItem tsItem in ((MenuStrip)c).Items)
{
GetAllMenuItems(items, tsItem);
}
}
ToolStripMenuItem found = items.Find(x => x.Name == s);
if (found != null) found.PerformClick();
}
}
void GetAllMenuItems(List<ToolStripMenuItem> items, ToolStripMenuItem menu)
{
items.Add(menu);
foreach(ToolStripMenuItem m in menu.DropDownItems)
GetAllMenuItems(items, m);
}
The ToolStripMenuItem is not considered a control, you must instead use its container
if(c is MenuStrip)
{
foreach(ToolStripMenuItem tsItem in ((MenuStrip)c).Items)
{
if (tsItem.Name == item)
{
tsItem.PerformClick();
}
}
}

Set the special property of multiple controls to the same value

How can I Set the special property of multiple controls to the same value?
For example set the visible property of all labels in the form to true.
I use this code but labels appear to have null values but they have values.
protected void Page_Load(object sender, EventArgs e)
{
foreach ( Label lbl in this.Controls.OfType<Label>()) {
if (lbl == null) continue;
lbl.Visible = false;
}
}
I should mention that I use master page.But I don't want to set the properties of my nested master pages. I want to set the properties of just current ASP page.
You may have some controls within others, so you need to call it recusrively....Here's a similat method I use..............
Notice at the end, I call it from within itself if the Control in question has controls of its' own....
Hope this helps.....
private void ClearControls(ControlCollection controlCollection, bool ignoreddlNewOrExisting = false)
{
foreach (Control control in controlCollection)
{
if (ignoreddlNewOrExisting)
{
if (control.ID != null)
{
if (control.ID.ToUpper() == "DDLNEWOREXISTING")
{
continue;
}
}
}
if (control is TextBox)
{
((TextBox)control).Text = "";
((TextBox)control).Font.Size = 10;
}
if (control is DropDownList)
{
((DropDownList)control).SelectedIndex = 0;
((DropDownList)control).Font.Size = 10;
}
if (control is CheckBox)
{
((CheckBox)control).Checked = false;
}
//A bit of recursion
if (control.Controls != null)
{
this.ClearControls(control.Controls, ignoreddlNewOrExisting);
}
}
}
Note that you can use following to avoid this ugly type check.:
foreach(Label lbl in this.Controls.OfType<Label>())
lbl.Visible= false;
But neither your nor my approach will enumerate all controls recursively. Only the controls which are on top of the page. So you won't find labels in nested controls(f.e. in a GridView) or which are in the MasterPage. Therefore you need a recursive method.
You could use this handy extension method:
public static class ControlExtensions
{
public static IEnumerable<Control> GetControlsRecursively(this Control parent)
{
foreach (Control c in parent.Controls)
{
yield return c;
if (c.HasControls())
{
foreach (Control control in c.GetControlsRecursively())
{
yield return control;
}
}
}
}
}
Then this readable code should hide all labels on the page and in the MasterPage:
var allLabels = this.GetControlsRecursively()
.Concat(this.Master.GetControlsRecursively())
.OfType<Label>();
foreach (Label label in allLabels)
label.Visible = false;
protected void Page_Load(object sender, EventArgs e)
{
SetAllLabelValue(this.Controls);
}
private void SetAllLabelValue(ControlCollection controls)
{
foreach (Control item in controls)
{
if (item.HasControls())
{
SetAllLabelValue(item.Controls);
}
Label lb = item as Label;
if (lb != null)
{
lb.Visible = false;
}
}
}

Getting a cell container from WPF ListView

I have a list view on a component which is bound to an observable collection of type BreakdownViewRow.
Each cell contains a component which operating in EDIT and DISPLAY modes.
I need to find a way to get to programatially change the mode on the cell content, but trying to iterate over the items in the list view returns objects of type BreakdownViewRow.
Is there a way I can access the cell containing each component, rather than getting back items as they exist in my observable collection?
The code for my component (the ContainerSelected event is bound in the XAML, and fires correctly passing the EditableControlContainer object as the sender):
public partial class ArrearsBreakdownView : UserControl
{
private ObservableCollection<BreakdownViewRow> rows;
public ObservableCollection<BreakdownViewRow> Rows {
get { return rows; }
set { rows = value; }
}
public BreakdownView() {
InitializeComponent();
rows = new ObservableCollection<BreakdownViewRow>();
Populate();
this.DataContext = this;
}
public void Populate() {
rows.Add(new BreakdownViewRow(2015, 1000.50M, "TE1 \t Test Code 1", "This is a test row"));
rows.Add(new BreakdownViewRow(2014, 100M, "TE1 \t Test Code 1", "Another row"));
rows.Add(new BreakdownViewRow(2013, 150M, "TE1 \t Test Code 1", "This is a test row"));
}
public void ContainerSelected(object sender, RoutedEventArgs e) {
EditableControlContainer ecc = (EditableControlContainer)sender;
foreach (ListViewItem item in grdArrears.Items) {
//Here, I get a BreakdownViewRow object, when what I need is the EditableControlContainer object,
//or the cell container
}
int stop = 1;
}
}
You can try using the ItemContainerGenerator. It'll return the container of the row, but you can then use the TreeViewHelper to get the ContentPresenters of each cell, and then look for your control inside each ContentPresenter's Template:
public void ContainerSelected(object sender, RoutedEventArgs e) {
EditableControlContainer ecc = (EditableControlContainer)sender;
ItemContainerGenerator generator = grdArrears.ItemContainerGenerator;
foreach (var item in grdArrears.Items) {
var itemContainer = generator.ContainerFromItem(item);
foreach (var presenter in GetChildrenOfType<ContentPresenter>(itemContainer))
{
var myControl = presenter.ContentTemplate.FindName("MyControl", presenter);
// Do stuff with your cell control
}
}
}
private IEnumerable<T> GetChildrenOfType<T>(DependencyObject parent) where T : DependencyObject
{
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child is T)
yield return (T)child;
var childrenOfType = GetChildrenOfType<T>(child);
foreach (var childOfType in childrenOfType)
yield return childOfType;
}
}

Is a List<> of variables possible?

This is probably a long shot, but I'm trying to minimize the repition in the program I'm working on, and have run into a snag. As can be seen in the ClearTextBoxes() method below, I have a very repetitive bit of code that I would prefer to place inside a foreach loop for succinctness. (Originally the foreach (object box in customBoxes) loop was not there). I tried to do this with the following List, but to no avail. I'm not sure if this is just not possible to do, or if I'm simply doing it wrong. I would appreciate any help you could give, and if this can't be done, then how can I shrink this code block?
Thanks!
List<object> customBoxes = new List<object>();
customBoxes.AddRange(new[] { "TextBox", "DateBox", "DigitBox", "PhoneBox", "WaterTextBox" });
public void ClearTextBoxes()
{
ChildControls ccChildren = new ChildControls();
foreach (object o in ccChildren.GetChildren(rvraDockPanel, 2))
{
foreach (object box in customBoxes)
{
if (o.GetType() == typeof(TextBox))
{
TextBox txt = (TextBox)o;
txt.Text = "";
}
if (o.GetType() == typeof(DigitBox))
{
DigitBox digit = (DigitBox)o;
digit.Text = "";
}
if (o.GetType() == typeof(PhoneBox))
{
PhoneBox phone = (PhoneBox)o;
phone.Text = "";
}
if (o.GetType() == typeof(DateBox))
{
DateBox date = (DateBox)o;
date.Text = "";
}
if (o.GetType() == typeof(WatermarkTextBox))
{
WatermarkTextBox water = (WatermarkTextBox)o;
water.Text = "";
}
}
}
}
List<Type> customBoxes = new List<Type>();
customBoxes.AddRange(new[] { typeof(PhoneBox), typeof(DigitBox), ....." });
foreach (Control c in this.Controls)
{
if (customBoxes.Contains(c.GetType()))
{
c.Text = string.Empty;
}
}
I would create an interface with a ClearText() method.
interface IClearable
{
public void ClearText();
}
Then you can inherit from each control and apply that interface:
class ClearableDigitBox : DigitBox, IClearable
{
public void ClearText() {
Text = String.Empty;
}
}
// etc...
So it's just:
var list = new List<IClearable>;
// ...
foreach (IClearable control in list) control.ClearText();
You could use reflection in some way to mimic some ductyping behavior but i wouldnt go for that solution since it's not performant and ugly.
foreach (object box in customBoxes)
{
var boxType = box.GetType();
var textProperty = boxType.GetProperty("Text");
if (textProperty != null && textProperty.CanWrite)
{
textProperty.SetValue(box, "", null);
}
}
Or you can use dynamic to achieve the same result:
foreach (dynamic box in customBoxes)
{
box.Text = "";
}
The way to go would be to make your custom controls implement a single interface IWithTextProperty which ofcourse exposes the text property.
Aren't all the input boxes a part of Control object?
if so, and you want to clear all the text from the controls
then i would probably have a method like:
public void ClearText(List<Control> items)
{
foreach (Control control in items)
{
control.Text = string.Empty;
}
}
if you just want to locate controls of a specific type
public void ClearText(List<Control> items)
{
foreach (Control control in items)
{
if (control is TextBox)
((TextBox)control).Text = string.Empty;
else if (control is DigitBox)
((DigitBox)control).Text = string.Empty;
else
{ // Handle anything else.}
}
}
In response to a couple of the replies so far, this is the class file I have for the custom boxes. The NumberTextBox class is the default snippet that VS added. I haven't used it, just haven't deleted it either. In addition to the DateBox(which is collapsed to save space) class, there is also a PhoneBox class that inherits from DigitBox as well. the WatermarkTextBox class that DigitBox inherits from is in the WpfToolkit.Extended.dll. The only real difference in these classes is that each adds a method to allow/disallow formatting keys being pressed (parenthesis, periods, hyphens, etc).
This class basically came about as a result of trying to merge several different snippets I found around the web, but the purpose of these boxes is to enable a watermark and also restrict the characters that can be entered into those boxes.
public class NumberTextBox : Control
{
static NumberTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumberTextBox), new FrameworkPropertyMetadata(typeof(NumberTextBox)));
}
}
public class DigitBox : WatermarkTextBox, IClearable
{
#region Constructors
///<summary>
///The default constructor
/// </summary>
public DigitBox()
{
TextChanged += new TextChangedEventHandler(OnTextChanged);
KeyDown += new KeyEventHandler(OnKeyDown);
PreviewKeyDown += new KeyEventHandler(OnPreviewDown);
}
#endregion
#region Properties
new public String Text
{
get { return base.Text; }
set
{
base.Text = LeaveOnlyNumbers(value);
}
}
#endregion
#region Functions
public bool IsNumberKey(Key inKey)
{
if (inKey < Key.D0 || inKey > Key.D9)
{
if (inKey < Key.NumPad0 || inKey > Key.NumPad9)
{
return false;
}
}
return true;
}
public bool IsActionKey(Key inKey)
{
return inKey == Key.Delete || inKey == Key.Back || inKey == Key.Tab || inKey == Key.Return;
}
public string LeaveOnlyNumbers(String inString)
{
String tmp = inString;
foreach (char c in inString.ToCharArray())
{
if (!IsDigit(c))
{
tmp = tmp.Replace(c.ToString(), "");
}
}
return tmp;
}
public bool IsSpaceKey(Key inKey)
{
if (inKey == Key.Space)
{
return true;
}
return false;
}
public bool IsDigit(char c)
{
return (c >= '0' || c <='9');
}
#endregion
#region Event Functions
protected virtual void OnKeyDown(object sender, KeyEventArgs e)
{
e.Handled = !IsNumberKey(e.Key) && !IsActionKey(e.Key) && !IsSpaceKey(e.Key);
}
protected virtual void OnTextChanged(object sender, TextChangedEventArgs e)
{
base.Text = LeaveOnlyNumbers(Text);
}
protected virtual void OnPreviewDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
{
e.Handled = true;
}
}
#endregion
}
public class DateBox : DigitBox

Categories

Resources