WPF put XAML refrences into a c# list - c#

Right now I have 15 items, that I have to set the value to one by one, is there a way I can put all the refrences into one c# list or something, so I could loop through it?
//TITLES
BTitle0.Text = Items[14]["title"];
BTitle1.Text = Items[13]["title"];
BTitle2.Text = Items[12]["title"];
BTitle3.Text = Items[11]["title"];
BTitle4.Text = Items[10]["title"];
BTitle5.Text = Items[9]["title"];
BTitle6.Text = Items[8]["title"];
BTitle7.Text = Items[7]["title"];
BTitle8.Text = Items[6]["title"];
BTitle9.Text = Items[5]["title"];
BTitle10.Text = Items[4]["title"];
BTitle11.Text = Items[3]["title"];
BTitle12.Text = Items[2]["title"];
BTitle13.Text = Items[1]["title"];
BTitle14.Text = Items[0]["title"];
Basically I want to have a list to XAML refrences like BTitle[0].text..., Is there any way to do that?

Try the FindName method of the window or control that hosts the TextBox elements:
for (int i = 0; i < 15; i++)
{
TextBox textBox = FindName("BTitle" + i) as TextBox;
if (textBox != null)
{
textBox.Text = "...";
}
}
Or use an ItemsControl that binds to the items.

Related

C# (UWP) - Access object dynamically from string-variable

So I've written some code that creates TextBlocks from a list of strings by calling a for loop:
List<string> menuPages = new List<string>() { "Home", "Media", "Settings" };
//method called from constructor:
private void createHeaders ()
{
for (int i=0; i<menuPages.Count; i++)
{
TextBlock iheader = new TextBlock();
iheader.Name = menuPages[i];
iheader.Text = menuPages[i];
if (i==pageIndex)
{ iheader.FontSize = 36; }
else
{ iheader.FontSize = 32; }
stacky.Children.Add(iheader); //Adding button to stack panel
}
}
Now I've been writing another method that would cycle through each TextBlock in a loop and change the text to whatever I intend. I'd gotten a foreach loop working for the stackPanel children: (TextBlock tBlock in stacky.Children)
but I need to work with an indexed for loop. The code below is how I WANT to achieve this:
//Re-render headers
for (int i = 0; i < menuPages.Count; i++)
{
//TextBlock menuPages[i].text = "foo";
}
Now of course the syntax above doesn't work so my question is, how can I address the TextBlocks from the strings in a list?
Just have your textblocks created in a list. So, you can manipulate easily with indexed forloop.
List<string> menuPages = new List<string>() { "Home", "Media", "Settings" };
List<TextBlock> textBlocks = new List<TextBlock>();
public MainPage()
{
this.InitializeComponent();
createHeaders();
}
private void createHeaders()
{
for (int i = 0; i < menuPages.Count; i++)
{
TextBlock iheader = new TextBlock();
iheader.Name = menuPages[i];
iheader.Text = menuPages[i];
iheader.FontSize = 32;
textBlocks.Add(iheader);
Stacky.Children.Add(iheader);
}
}
private void change_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < textBlocks.Count; i++)
{
textBlocks[i].Text = "foo";
}
}
If the StackPanel only contains the TextBlock elements you are adding dynamically, you can access them this way as well:
foreach (var textBlock in Stacky.Children.OfType<TextBlock>())
{
textBlock.Text = "something";
}
This approach uses the OfType<T> LINQ extension method which filters the input collection by the specified type, so it only returns those children of Stacky that are a TextBlock.
If you have more content, in the StackPanel, then #Vignesh G's answer is the way to go.

Flow Layout Panel Population C#

I'm trying to populate a Flow Layout Panel with ComboBoxes and NumbericUpDowns.
The problem I'm having is using both the new NumbericUpDowns with the new ComboBoxes. Here is how I'm generating the ComboBoxes and NumericUpDowns.
// This int increments each time the code is run. It's located outside of the method below.
int captchaID = 0;
.
// Textboxes that are only for the UI, no code interaction based on text input.
string textboxText = "captchaTextbox";
TextBox newTextbox = new TextBox();
newTextbox.Name = captchaID.ToString() + textboxText;
newTextbox.Text = "";
newTextbox.Width = 175;
itemFlowPanel.Controls.Add(newTextbox);
// Combo Boxes
string comboBoxText = "captchaComboBox";
ComboBox newComboBox = new ComboBox();
newComboBox.Name = captchaID.ToString() + comboBoxText;
newComboBox.Width = 50;
newComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
itemFlowPanel.Controls.Add(newComboBox);
// This array holds my strings that are added to each ComboBox
string[] skills = new string[6];
skills[0] = "STR";
skills[1] = "DEX";
skills[2] = "CON";
skills[3] = "INT";
skills[4] = "WIS";
skills[5] = "CHA";
// This for loop is just populating my ComboBox with the array.
for (int i = 0; i < skills.Length; i++)
{
newComboBox.Items.Add(skills[i]);
}
// Numeric Up Downs
string numericUpDownText = "captchaNumericUpDown";
NumericUpDown newNumericUpDown = new NumericUpDown();
newNumericUpDown.Name = captchaID.ToString() + numericUpDownText;
newNumericUpDown.Width = 50;
newNumericUpDown.ValueChanged += new EventHandler(captchaNumericUpDown_Click);
newNumericUpDown.ValueChanged += new EventHandler(captchaNumericUpDown_ValueChanged);
itemFlowPanel.Controls.Add(newNumericUpDown);
captchaID++;
With the current code, I'm able to edit an EventHandler that each NumericUpDown contains, but I haven't found a way to make it able to read it's corresponding combobox (which increment together with captchaID).
What I'd like to be able to do, is create a new unique event for each, but if that's not possible, a way to check the ID of the combobox would help as well.
Here are quick solutions:
1) By using dictionary
Dictionary<NumericUpDown, ComboBox> _controls = new Dictionary<NumericUpDown, ComboBox>();
// when you create comboBox - add entry with associated numericUpDown
_controls.Add(numericUpDown1, comboBox1);
// now in the numericUpDown event you can get combobox like this
void numericUpDown_Whatever(object sender, WhateverEventArgs e)
{
var numericUpDown = (NumericUpDown)sender;
var comboBox = _controls[numericUpDown];
// do something
var selectedIndex = comboBox.SelectedIndex;
...
}
2) By using Tag
// add combobox into numericUpDown Tag when you create them
numericUpDown1.Tag = comboBox1;
// now in the numericUpDown event you can get combobox like this
void numericUpDown_Whatever(object sender, WhateverEventArgs e)
{
var numericUpDown = (NumericUpDown)sender;
var comboBox = (CombBox)numericUpDown.Tag;
// do something
var selectedIndex = comboBox.SelectedIndex;
...
}
You can rewrite your captchaNumericUpDown_ events to take a ComboBox as an additional parameter and then call them like this:
newNumericUpDown.ValueChanged += (sender, args) =>
{
captchaNumericUpDown_Click(sender, args, newComboBox);
}

Iterating through fields?

First of all, I'm not entirely sure how to phrase this or what to search for if someone asked before.
Say I have multiple labels: label1, label2, label3, label4, etc...
Now, I know this works in PHP so I'm wondering if there is a way to do this in C# -
Can I somehow iterate through these labels to set their values in a loop?
i.e.
string[] something = new string[3] { "text", "text", "text" };
for (int i = 0; i < something.length; i++)
{
labels(i).Text = something[i];
}
You can use Controls.Find() method for finding the Label Control by its Control Name.
Try This:
for (int i = 0; i < something.length; i++)
{
((Label) Controls.Find("lablel"+i,true)[0]).Text = something[i];
}
You can get an enumerable list of labels from the Controls collection by using .OfType<>
e.g.
foreach(Label l in this.Controls.OfType<Label>())
{
...
}
Or simply find all the labels without needing to know their names:
foreach (Control ctrl in this.Controls)
{
Label label = ctrl as Label;
if (label != null)
{
label.Text = "";
}
}
You could use Controls.Find to find all references:
for (int i = 0; i < something.length; i++)
{
var lbl = this.Controls.Find("lable" + i, true);
if(lbl.Length > 0)
((Label)lbl[0]).Text = something[i];
}
Another approach using LINQ (which doesn't search recursively as opposed to Find):
for (int i = 0; i < something.Length; i++)
{
Label lbl = this.Controls.Cast<Label>()
.FirstOrDefault(l => l.Name.Equals("lable" + i, StringComparison.InvariantCultureIgnoreCase));
if(lbl != null) lbl.Text = something[i];
}
However, i would not call this good practise. Your array and the labels are directly related to each other. What hapens if you change the array but forget to change the labels?
You should use a different control like ListBox or DataGridView or create the labels dynamically according to the size of the array.

how to save data from dynamic textbox?

this code creates a textbox dynamically based on the total number of items in a listview. my problem is how can i access these textboxes so i can save the contents of the textbox to my database?
int f = 24;
int j = 25;
for (int gg = 0; gg < listView1.Items.Count;gg++ )
{
j = f + j;
TextBox txtb = new TextBox();
txtb.Name = "tboxl1"+gg;
txtb.Location = new Point(330,j);
txtb.Visible = true;
txtb.Enabled = true;
txtb.Font = new Font(txtb.Font.FontFamily,12);
groupBox2.Controls.Add(txtb);
}
I'd be more inclined to write you code like this:
var f = 24;
var j = 25;
var textBoxes =
Enumerable
.Range(0, listView1.Items.Count)
.Select(gg =>
{
j = f + j;
var txtb = new TextBox();
txtb.Name = String.Format("tboxl1{0}", gg);
txtb.Location = new Point(330, j);
txtb.Visible = true;
txtb.Enabled = true;
txtb.Font = new Font(txtb.Font.FontFamily, 12);
return txtb;
})
.ToList();
textBoxes.ForEach(txtb => groupBox2.Controls.Add(txtb));
Now you have a variable textBoxes that saves references to the new text boxes. You can use that to get the values from the text boxes to save them to your database.
If you want all TextBox controls then:
foreach (Control control in groupBox2.Controls)
{
if (control is TextBox)
{
string value = (control as TextBox).Text;
// Save your value here...
}
}
But if you want a specific TextBox, you can get it by its name like this:
Control control = groupBox1.Controls.Find("textBox1", false).FirstOrDefault(); // returns null if no control with this name exists
TextBox textBoxControl = control as TextBox; // if you want TextBox control
string value = control.Text;
// Now you can save your value anywhere
You can get the reference to text box as follows,
Control GetControlByName(string Name)
{
foreach(Control c in this.Controls)
if(c.Name == Name)
return c;
return null;
}

how to add items to TreeViewAdv in multi-column mode with winforms

I was playing around with this control called TreeViewAdv. I've already added the control and added couple of columns trying to see how it works. but till now when I add items to the control all I get is empty nodes. the example provided with the control is not clear at all and it just gave me headaches when I try to figure out how the data is being added to it. anyway here is what I've done so far and I hope that someone can guide me to the right direction.
TreeModel _model = new TreeModel();
treeViewAdv1.Model = _model;
treeViewAdv1.BeginUpdate();
for (int i = 0; i < 20; i++)
{
Node parentNode = new Node("root" + i);
_model.Nodes.Add(parentNode);
for (int n = 0; n < 2; n++)
{
Node childNode = new MyNode("child" + n);
parentNode.Nodes.Add(childNode);
}
}
treeViewAdv1.EndUpdate();
anyway, all I'm getting is empty nodes and I really can't figure out how to add data to the other columns... any help would be appreciated...
Obviously this questions is old, but I was unable to find any answers to this question, so I figured I would try to save someone some future frustration.
To get multiple columns to display, first change the UseColumns property to true.
Then add desired columms to the Columns collection property.
Next using the NodeControls collection property to create a list of the types of data that will be shown, and how they should be formatted (Checkbox, TextBox, etc). Make sure to set 1) the DataPropertyName (will be used later), 2) the ParentColumn (to show which column in the treeView is supposed to show the data.
Finally, create a new class inheriting from the Node class, and add a public property with the same name as each NodeControl. Then when adding Nodes, use your new class with the correct value.
private class ColumnNode: Node
{
public string NodeControl1=""; // This sould make the DataPropertyName specified in the Node Collection.
public string NodeControl2 = "";
public string NodeControl3 = "";
public ColumnNode(string nodeControl1, string nodeControl2, int nodeControl3)
{
NodeControl1 = nodeControl1;
NodeControl2 = nodeControl2;
NodeControl3 = nodeControl3.ToString();
}
}
Then when adding the
TreeModel _model = new TreeModel();
_treeViewAdv.Model = _model;
_treeViewAdv.BeginUpdate();
for (int i = 0; i < 20; i++)
{
Node parentNode = new ColumnNode("root" + i, "",0);
_model.Nodes.Add(parentNode);
for (int n = 0; n < 2; n++)
{
Node childNode = new ColumnNode("child" + n,"Further Information",1);
parentNode.Nodes.Add(childNode);
}
}
_treeViewAdv.EndUpdate();
For reference, the designer code for the treeViewAdv in this case would look like this:
private Aga.Controls.Tree.TreeViewAdv _treeViewAdv;
private Aga.Controls.Tree.TreeColumn Column1;
private Aga.Controls.Tree.TreeColumn Column2;
private Aga.Controls.Tree.TreeColumn Column3;
private Aga.Controls.Tree.NodeControls.NodeTextBox NodeControl1;
private Aga.Controls.Tree.NodeControls.NodeTextBox NodeControl2;
private Aga.Controls.Tree.NodeControls.NodeTextBox NodeControl3;
private InitializeComponent()
{
// Left out all other initialization, since this was long enough already.
this.treeViewAdvPrint = new Aga.Controls.Tree.TreeViewAdv();
this.Column1 = new Aga.Controls.Tree.TreeColumn();
this.Column2 = new Aga.Controls.Tree.TreeColumn();
this.Column3 = new Aga.Controls.Tree.TreeColumn();
this.NodeControl1 = new Aga.Controls.Tree.NodeControls.NodeTextBox();
this.NodeControl2 = new Aga.Controls.Tree.NodeControls.NodeTextBox();
this.NodeControl3= new Aga.Controls.Tree.NodeControls.NodeTextBox();
//
// _treeViewAdv
//
this._treeViewAdv.BackColor = System.Drawing.SystemColors.Window;
this._treeViewAdv.Columns.Add(this.Column1);
this._treeViewAdv.Columns.Add(this.Column2);
this._treeViewAdv.Columns.Add(this.Column3);
this._treeViewAdv.DefaultToolTipProvider = null;
this._treeViewAdv.DragDropMarkColor = System.Drawing.Color.Black;
this._treeViewAdv.GridLineStyle = ((Aga.Controls.Tree.GridLineStyle)((Aga.Controls.Tree.GridLineStyle.Horizontal | Aga.Controls.Tree.GridLineStyle.Vertical)));
this._treeViewAdv.LineColor = System.Drawing.SystemColors.ControlDark;
this._treeViewAdv.Location = new System.Drawing.Point(12, 12);
this._treeViewAdv.Model = null;
this._treeViewAdv.Name = "_treeViewAdv";
this._treeViewAdv.NodeControls.Add(NodeControl1);
this._treeViewAdv.NodeControls.Add(NodeControl2);
this._treeViewAdv.NodeControls.Add(NodeControl3);
this._treeViewAdv.SelectedNode = null;
this._treeViewAdv.Size = new System.Drawing.Size(443, 356);
this._treeViewAdv.TabIndex = 6;
this._treeViewAdv.Text = "_treeViewAdv";
this._treeViewAdv.UseColumns = true;
//
// Column1
//
this.Column1.Header = "Column 1";
this.Column1.SortOrder = System.Windows.Forms.SortOrder.None;
this.Column1.TooltipText = null;
this.Column1.Width = 290;
//
// Column3
//
this.Column3.Header = "Column 3";
this.Column3.SortOrder = System.Windows.Forms.SortOrder.None;
this.Column3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.Column3.TooltipText = null;
//
// Column2
//
this.Column2.Header = "Column 2";
this.Column2.SortOrder = System.Windows.Forms.SortOrder.None;
this.Column2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.Column2.TooltipText = null;
this.Column2.Width = 91;
//
// NodeControl1
//
this.NodeControl1.DataPropertyName = "NodeControl1";
this.NodeControl1.IncrementalSearchEnabled = true;
this.NodeControl1.LeftMargin = 3;
this.NodeControl1.ParentColumn = this.Column1;
//
// NodeControl2
//
this.NodeControl2.DataPropertyName = "NodeControl2";
this.NodeControl2.IncrementalSearchEnabled = true;
this.NodeControl2.LeftMargin = 3;
this.NodeControl2.ParentColumn = this.Column2;
//
// NodeControl3
//
this.NodeControl3.DataPropertyName = "NodeControl3";
this.NodeControl3.IncrementalSearchEnabled = true;
this.NodeControl3.LeftMargin = 3;
this.NodeControl3.ParentColumn = this.Column3;
}
It seems as though the price of entry for using this fantastic control is hours, and hours, of head scratching frustration.
This is what you need to do:
private void Form1_Load(object sender, EventArgs e)
{
TreeModel _model = new TreeModel();
treeViewAdv1.Model = _model;
treeViewAdv1.BeginUpdate();
for (int i = 0; i < 20; i++)
{
Node parentNode = new Node("root" + i);
_model.Nodes.Add(parentNode);
for (int n = 0; n < 2; n++)
{
Node childNode = new Node("child" + n);
parentNode.Nodes.Add(childNode);
}
}
NodeTextBox ntb = new NodeTextBox();
ntb.DataPropertyName = "Text";
this.treeViewAdv1.NodeControls.Add(ntb);
treeViewAdv1.EndUpdate();
}
Just in case you're still struggling with the issue, or anyone else is having the same trouble: the solution to empty nodes is to assign a view component to tree.
TreeViewAdv uses MVC, and it requires that you assign a view, though this is not obvious from the example project. NodeTextBox class under NodeControls folder in the source of the TreeViewAdv is one of the viewers you can use. You need to add it to your form and connect it to tree control through its DataPropertyName attribute like this:
this._tBox.DataPropertyName = "Text";
where _tBox is the NodeTextBox instance. Needless to say, I've just lost hours figuring this out. Hope it helps someone else.
You need to instantiate your columns first, then attach them to the TreeView. After all add new cells in all columns at same cell index.
Hope to help

Categories