How to create an array of Circular Progress Bars? - c#

I would like to know how can I create an array of Circular Progress Bars and access its properties within the array, like CircularProgressBar[i].text and CircularProgressBar[i].value.
I tried to use object array but I can't access the properties of circular progress bar within the for loop, what I also tried is to make to arrays one is type string and it has all the CircularProgressBars.text, and the Other one is the type INT which contains CircularProgressBar.value, but it didn't work, nothing changed in the form.
CircularProgressBar.CircularProgressBar[] cbpArray = new CircularProgressBar.CircularProgressBar[] { shifts1.circularProgressBarNeeShift1, shifts1.circularProgressBarNeeShift2, shifts1.circularProgressBarNeeShift1 };
public Form1()
{
InitializeComponent();
}
image

Okay, since you are trying to reference an item that is in a user control you need to add an accessor inside your UserControl .cs file. I believe it is called shift1.cs for you.
Note: cpb is the name that I gave the CircularProgressBar inside the UserControl shifts1.
public partial class shifts1 : UserControl
{
public CircularProgressBar.CircularProgressBar CPB
{
get
{
return cpb;
}
set
{
cpb = value;
}
}
public shifts1()
{
InitializeComponent();
}
}
Then you will use the name for each user control from your form. In my case I named mine formCPB1 and formCPB2.
CircularProgressBar.CircularProgressBar[] arr = new CircularProgressBar.CircularProgressBar[]
{ formCPB1.CPB, formCPB2.CPB };
Once you have the array you can access them by using the name of the array.
arr[0].Text = "test";
arr[1].Text = "asdf";

Related

How to make a class that waits for instance to be created to instantiate variables?

I am trying to create a class with some subclasses for a color management system in my application.
I need to create a "Colorset" object that has some "Category" objects inside of it. The problem is I need to access members of one of the categories from another category.
Since I want to be able to set the values of the "Category" members when instantiating a new "Colorset", I can't make them static.
Here's an example of what I want to do.
public class Colorset
{
public General General { get; set; }
public Page Page { get; set; }
}
public class General
{
public Color Primary = Color.FromArgb("#399ed6");
public Color Secondary = Color.FromArgb("#fff");
public Color Text = Color.FromArgb("#000");
}
public class Page
{
public Color TitleBar = General.Primary; // General not static, cant access it
public Color TitleBarText = General.Secondary;
}
I want to set the TitleBar value to the value of "Primary" FROM THE COLORSET PARENT. I know a Page will always have a Colorset parent, and I want to access the value of Primary that has been set in the parent colorset.
This would be an example on how I want to instantiate a new Colorset:
Colorset = new()
{
General = new()
{
Primary = Color.FromArgb("#fff"),
Secondary = Color.FromArgb("#000")
}
Page = new()
{
TitleBar = Color.FromArgb("#123")
// Since TitleBarText not set it defaults to the value of "Secondary"
}
How can I achieve something like this?
Thanks in advance
create a constructor for Page that accepts a General parameter
public Page(General general)
{
TitleBarText = general.Secondary;
}
and pass in the reference when ColorSet creates Page
Page = new Page(this.General);

How to properly declare class variables (CUIT Controls)

I am setting up Coded UI Tests for WPF application and I want to use code approach instead of record-and-generate-code approach. I'd like to use page objects trough code and I need to declare control (buttons, tabs, etc.) variables in page objects that would be used by multiple functions.
I tried declaring the variable in a class and adding properties in constructor (pendingButton1)
and creating function which returns the control and assigning to a variable in a class (pendingButton2) but neither worked.
It works when I declare the variable (or create the variable by function) within the function that I want to use the variable in (pendingButton3 and 4).
public partial class Press : Header
{
WpfToggleButton pendingButton1 = new WpfToggleButton(_wpfWindow);
WpfToggleButton pendingButton2 = Controls.Press.getPendingButton(_wpfWindow);
public Press(WpfWindow wpfWindow):base(wpfWindow)
{
this.pendingButton1.SearchProperties[WpfControl.PropertyNames.AutomationId] = "Tab1Button";
}
public void clickPendingButton() {
WpfToggleButton pendingButton3 = new WpfToggleButton(_wpfWindow);
pendingButton3.SearchProperties[WpfControl.PropertyNames.AutomationId] = "Tab1Button";
WpfToggleButton pendingButton4 = Controls.Press.getPendingButton(_wpfWindow);
Mouse.Click(pendingButton1); //UITestControlNotFoundException
Mouse.Click(pendingButton2); //UITestControlNotFoundException
Mouse.Click(pendingButton3); //This works
Mouse.Click(pendingButton4); //This works
}
}
I'd like to make it work when I declare the pendingButton outside clickPendingButton() function since it is used in multiple other functions.
The helper function Controls.getWpfButton() return just properties of the button, not "real" button. It has to be used in a constructor, then it can be used anywhere within the class. I wouldn't say its best practice but it works for me.
Press.cs
public partial class Press : SharedElements
{
private WpfButton pendingButton;
public Press(WpfWindow wpfWindow):base(wpfWindow)
{
pendingTab = Controls.getWpfButton(_wpfWindow, "Tab1Button");
}
public void clickPendingButton() {
Mouse.Click(pendingButton);
}
}
Controls.cs
internal static WpfButton getWpfButton(WpfWindow wpfWindow, string AutomationId)
{
WpfButton button = new WpfButton(wpfWindow);
button.SearchProperties[WpfControl.PropertyNames.AutomationId] = AutomationId;
return button;
}
What you want appears to be exactly the sort f code that the Coded UI record and generate tool generates. It creates many pieces of code that have a structure of the following style:
public WpfToggleButton PendingButton
{
get
{
if ((this.mPendingButton == null))
{
this.mPendingButton = new WpfToggleButton( ... as needed ...);
this.mPendingButton.SearchProperties[ ... as needed ...] = ... as needed ...;
}
return this.mPendingButton;
}
}
private WpfToggleButton mPendingButton;
This code declares the button as the class property PendingButton with a private supporting field that has an initial and default value of null. The first time that property is needed the get code executes the required search and saves the found control in the private field. That value is then returned in each subsequent usage of the property. Note that assigning null to the supporting field can be done to cause a new search, as demonstrated in this Q&A.

How to fill a Combobox from foreach in a different class

I am trying to fill a comboBox and a secondary form from a separate class file and I think I have the basics wrong.
The following is shortened to show the bones of what I have and what I think I may be doing wrong. I am not sure if I should be using List<> to populate the comboBox or an Array and suspect in either case my method declaraction is wrong and I cannot find a reference to the comboBox to populate from within the foreach loop.
OK the program.cs for my settings Form. This is not the main form but is the one I am looking to populate when a user select the comboBox.
Program.cs
class Settings
{
public partial class Settings : Form
{
// a bunch of String declarations used throughout
public Settings()
{
InitializeComponent();
}
}
}
The method within a class in a separate file is
Functions.cs
class functions
//This is a separate class to the Settings Form but same namespace.
{
//some global variables here
public string getDomain(string webURL)
{
//more variable declarations
//webURL is a value from the Settings Form
//code to send query to website, get the response and filter the response.
//This is the response filter
foreach (XmlNode node in xmlDoc.SelectNodes("//DAV:domains/DAV:domain", nsmgr))
{
strNode = node.InnerText;
responseString += strNode + " ";
list.Add(strNode);
//I would like to simply Add.Items(strNode) to the Settings.Form.cbxDomains but not as simple as this.
}
//this returns all the correct information as a space separated string.
return responseString;
}
}
From Update UI from a different thread in a different class
I thinks there are 2 things I should do.
1. change the form initialisation from InitilizeComponents() to
settingsWindow = new MyForm();
Application.Run(form);
Then simply call Settings.settingsWindow.cbxDomain.Add>items(responseString);
But do I also need to change the actual method to something like
public void List<String> getDomain(string webURL)
I am so confused. Most examples show it the other way of updating the class from the combo not the other way and some say create it as an array.
I actually think it could even be trimmed down further into one or 2 lines instead of the foreach, but that is way beyond my skillset at this time.
Here is how you could populate your combobox from another form.
I will use example since I do not know you code structure but you will get the point.
public class User //Custom generic class
{
public int _Id { get; set; }
public string _Name { get; set; }
}
public class Functions
{
public static List<User> PopulateComboboxWithUsers()
{
List<User> list = new List<User>();
foreach(var something in somethingBig) //You can change this if you re reading form XML with it's variables or something else
{
list.Add(new User { _Id = something.Id, _Name = something.Name };
}
return list;
}
}
public class Settings
{
public Settings()
{
InitializeComponents();
comboBox1.DataSource = Functions.PopulateComboboxWithUser();
comboBox1.DisplayMember = "_Name";
comboBox1.ValueMember = "_Id";
}
}
Other approach is to do the same function expect you will pass comboBox to it and you will do assigning inside it but I think this is more flexible.

How to add items to a list in C# using a class containing public variables

I hope you can help out a fellow programmer. Basically, I want the user input from the Rich Text Box (taskNameRTB) to be assigned to the taskName; string variable in my class taskStructure which is in form1 shown below:
public partial class Form1 : Form
{
public class taskStructure
{
public string taskName;
public string taskDescription;
public int Priority;
public string dateAndTime;
}
public List<taskStructure> TasksArray = new List<taskStructure>(); //Declared a list data structure
In my second form which is where the user enters everything related to the task, I want to send this information to the list after the 'Create Task' button has been clicked:
private void createTaskBtn_Click(object sender, EventArgs e)
{
Form1 welcomeForm = new Form1();
welcomeForm.TasksArray[0].taskName = taskNameRTB.Text;
welcomeForm.TasksArray[0].taskDescription = taskDescRTB.Text;
}
However, when I do this I get a ArgumentOutOfRangeException and I do not understand why. I have also tried these:
welcomeForm.TasksArray[0].Add(taskDescRTB.Text);
welcomeForm.TasksArray.Insert(0, taskNameRTB.Text);
welcomeForm.TasksArray.Add(taskDescRTB.Text);
taskNameRTB.Text = welcomeForm.TasksArray[0].taskName;
But the ones that run come up with the same error ArgumentOutOfRangeException and some of them don't work, such as:
welcomeForm.TasksArray[0].Add(taskDescRTB.Text);
I'm aware that the list has not been initialized, but how can I initialize it when it doesn't allow me to initialize it with user input...
Any light you can shed on this will be really helpful
Kind Regards,
Kieran
You need to add a new taskStructrue to the list.
welcomeForm.TasksArray.Add(new taskStructure
{
taskName = taskDescRTB.Text,
taskDescription = taskDescRTB.Text
});
But personally I'd rewrite that class to follow naming conventions and to use properties instead of public fields.
public class TaskStructure
{
public string TaskName { get; set; }
public string TaskDescription { get; set; }
public int Priority { get; set; }
public string DateAndTime { get; set; }
}
have you tried
welcomeForm.TasksArray.Add(new taskStructure(taskDescRTB.Text));
I don't know what taskStructure is, but you need to fill TasksArray with types of it.
Your TaskStructure is a class, and you are putting all TaskStructure objects into a list,
public List<taskStructure> TasksArray = new List<taskStructure>(); //Declared a list data structure
Does your Form1() have a constructor that calls InitializeComponents()?
If so, you could try adding TasksArray = new List<taskStructure>() right below InitializeComponents(), because it looks like you're trying to access the list data structure that hasn't been initialized with new.
Alternatively
As another user noted, you can create a constructor class for TaskStructure like this:
public TaskStructure(RTB rtb1, rtb2, rtb3) //where RTB is the rich text box type
{
taskName = rtb1.text;
taskDescription = rtb2.text;
//and so on.
}
Then you can do TaskArray.add(new TaskStruture(rtb1,rtb2,rtb3).
Thrid Edit
Just realized your TaskArray is actually a List, which in C# (and Java), you cannot access it with an index like TaskArray[0], you have to use getter and setter methods, which in this case is TaskArray.add(), and TaskArray.get(0), you're getting ArgumentOutOfRangeException because you're trying to access a List using square indexes like this --> [0]. You can actually access a list doing list1, as pointed out by another user.
Here's a good tutorial on C# lists, by DotNetPerls

Make ComboBox accept only specific type

I currently have a ComboBox in my Windows Forms Application. In order to specify which values the ComboBox will contain, I set DataSource property of the ComboBox to some array so that ComboBox contains values from that array. I could also use Items.Add() to add new values to ComboBox. However, I want to make sure that ComboBox can be populated with objects of some specific type. So, if I have a class called X, then I want to make it so that only an array of type X can be used as a data source for the ComboBox. Right now, ComboBox accepts objects of type System.Object. How can I achieve it? Is there a property of ComboBox that I need to set to be equal to my data type's name? Or is there an event that will check whether an object added to my ComboBox is of the needed type and will throw an exception if not?
I was thinking of creating a new class as a subtype of ComboBox, and overriding the Add method of Items property so that Add checks whether its argument is of the needed type (not sure if and how I can do it). Even if I do that, there are still other ways to add new values into ComboBox (AddRange, CopyTo, etc.), so I think there should be a more elegant solution to this problem.
If you want to control the type of item that the ComboBox can contain, you could try creating a new class derived form ComboBox, but you'd run into the problem that it still has the ComboBox.ObjectCollection Items property which would still accept any type! And (unfortunately for your idea of overriding) the Add method isn't virtual.
The only practical solution that I could think of would be to abstract the ComboBox somehow. If this isn't shared code, I would recommend just creating a method that you would use to add items to the ComboBox. Something like:
// NOTE: All items that are added to comboBox1 need to be of type `SomeType`.
private void AddItemToComboBox(SomeType item)
{
comboBox1.Items.Add(item);
}
Any attempt to add a non-SomeType object to the ComboBox would be met with a compiler error. Unfortunately, there's no easy way to prevent someone from still adding a non-SomeType item to ComboBox.Items directly.
Again, if this isn't shared code, it shouldn't really be an issue.
You can hide Items property by your
own Items property of custom type which taking as parameter original ItemsCollection
Example class for testing
public class Order
{
public Int32 ID { get; set; }
public string Reference { get; set; }
public Order() { }
public Order(Int32 inID, string inReference)
{
this.ID = inID;
this.Reference = (inReference == null) ? string.Empty : inReference;
}
//Very important
//Because ComboBox using .ToString method for showing Items in the list
public override string ToString()
{
return this.Reference;
}
}
With next class I tried wrap ComboBox's items collection in own type.
Where adding items must be concrete type
Here you can add other methods/properties you need (Remove)
public class ComboBoxList<TCustomType>
{
private System.Windows.Forms.ComboBox.ObjectCollection _baseList;
public ComboBoxList(System.Windows.Forms.ComboBox.ObjectCollection baseItems)
{
_baseList = baseItems;
}
public TCustomType this[Int32 index]
{
get { return (TCustomType)_baseList[index]; }
set { _baseList[index] = value; }
}
public void Add(TCustomType item)
{
_baseList.Add(item);
}
public Int32 Count { get { return _baseList.Count; } }
}
Here custom combobox class derived from ComboBox
Added: generic type
public class ComboBoxCustomType<TCustomType> : System.Windows.Forms.ComboBox
{
//Hide base.Items property by our wrapping class
public new ComboBoxList<TCustomType> Items;
public ComboBoxCustomType() : base()
{
this.Items = new ComboBoxList<TCustomType>(base.Items);
}
public new TCustomType SelectedItem
{
get { return (TCustomType)base.SelectedItem; }
}
}
Next code used in the Form
private ComboBoxCustomType<Order> _cmbCustom;
//this method used in constructor of the Form
private void ComboBoxCustomType_Initialize()
{
_cmbCustom = new ComboBoxCustomType<Order>();
_cmbCustom.Location = new Point(100, 20);
_cmbCustom.Visible = true;
_cmbCustom.DropDownStyle = ComboBoxStyle.DropDownList;
_cmbCustom.Items.Add(new Order(0, " - nothing - "));
_cmbCustom.Items.Add(new Order(1, "One"));
_cmbCustom.Items.Add(new Order(2, "Three"));
_cmbCustom.Items.Add(new Order(3, "Four"));
_cmbCustom.SelectedIndex = 0;
this.Controls.Add(_cmbCustom);
}
Instead of overriding ComboBox (which wont work as stated in itsme86's answer) you could override usercontrol, add a combobox to this, and then only expose the elements that you wish to work with. Something similar to
public partial class MyComboBox<T> : UserControl where T: class
{
public MyComboBox()
{
InitializeComponent();
}
public void Add(T item)
{
comboBox1.Items.Add(item);
}
public IEnumerable<T> Items
{
get { return comboBox1.Items.Cast<T>(); }
}
}
Please note however that some pieces of automated software rely on access the the underlying controls however so this may cause some issues.
This approach never changes the Items of the combobox so they will still store as objects but when you access them, you are casting them to the correct type and only allowing them to be added of that type. You can create a new combobox via
var myCB = new MyComboBox<ItemClass>();

Categories