related to this topic:
https://stackoverflow.com/questions/15170054/context-hint-using-combobox
Is there a way I can use the strings in my separate class:
namespace KeyWord
{
public class KeyWord
{
//Definitions
public String[] keywords = { "abstract", "as", "etc." };
}
}
to mylistbox items in my mainform?
lb = new ListBox();
Controls.Add(lb);
ty in advance
Sure. Try something like this.
KeyWord kw = new KeyWord();
foreach (string str in kw.keywords)
{
lb.Items.Add(str);
}
Or you can use databinding.
Also, if all you're doing is getting an array of strings from that class, you might want to use a static property so you don't have to instantiate an instance of that object. I would recommend using properties either way for exposing public data, instead of a public field.
Here's an example of using a static property, instead:
public class KeyWord
{
// Private field, only accessible within this class
private static string[] _keywords = { "abstract", "as", "etc." };
// Public Static Property, accessible wherever
public static string[] Keywords
{
get { return _keywords; }
set { _keywords = value; }
}
}
Then:
foreach (string str in KeyWord.Keywords)
{
lb.Items.Add(str);
}
Notice, I didn't instantiate the class in this example (no new KeyWords())
Related
I have a stucture of classes and subclasses as follows:
public class Regions
{
public const string UNITEDSTATES = "United States";
public static string[] members = { UNITEDSTATES};
public static class UnitedStatesTypes
{
public const string STEEL = "steel";
public const string CONCRETE = "concrete";
public static string[] members = { STEEL, CONCRETE };
public static class SteelStandards
{
public const string A36 = "ASTM A36";
public static string[] members = { A36 };
public static class A36Grades
{
public const string GRADE_36 = "Grade 36";
public static string[] members = { GRADE_36 };
}
public static class ConcreteStandards
{
...
}
There are more values under each one of the classes, but this is just a small sample so you can get the idea of what it looks like. I am trying to create a UI to select each one of these. There are 4 dropdown menus, each menu is populated by the value of the higher menu. So if the standards dropdown is on SteelStandards, the next dropdown is populated with A36, if it was on ConcreteStandards the next would be populated with the data under ConcreteStandards. Is there a way that I can access a subclass using a string variable?
For example, the first dropdown will select United States. The next dropdown needs to piece together "UnitedStatesTypes" and then access Regions.UnitedStatesTypes.members. I have tried using braces
Regions["UnitedStatesTypes"].members
but this did not work. Is there a way to make this happen? Or is there a better way to organize my data?
You could do this with just dictionaries, albeit it gets a bit unwieldy as you go down the tree:
var regions = new Dictionary<string,Dictionary<string,Dictionary<string,Dictionary<string,List<string>>>>>();
// populate it. Yes I know how ugly that will look!
var usSteelStandards = regions["United States"]["Steel"]["Standards"];
A better way might be to refactor your code as a set of class instances, instead of trying to use static classes/members all the way. It is a typical tree structure
public class Node : IEnumerable<Node>
{
public Node(string text)
{
this.Text = text;
this.Children = new List<Node>();
}
public string Text {get; private set;}
public List<Node> Children { get; private set;}
public Node this[string childText]
{
get{ return this.Children.FirstOrDefault(x => x.Text == childText); }
}
public void Add(string text, params Node[] childNodes)
{
var node = new Node(text);
node.Children.AddRange(childNodes);
this.Children.Add(node);
}
public IEnumerator<Node> GetEnumerator()
{
return Children.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
This can then be setup and used much easier
var node = new Node("root")
{
{
"United States",
new Node("Steel")
{
{
"ASTM A36",
new Node("Grade 36")
}
},
new Node("Concrete")
{
}
}
};
Console.WriteLine(node["United States"].Children.Count);
Console.WriteLine(node["United States"]["Steel"]["ASTM A36"].Children[0].Text);
Live example: https://rextester.com/QVGN99585
I'm trying to add strings to a List<string> so I can print them with a loop in a certain point of time, being more specific here is part of my code:
public class Foo{
public string propertyA;
public string propertyB;
public string propertyC;
public List<string> list;
Public Foo(){
list = new List<string>();
list.Add(propertyA);
list.Add(propertyB);
list.Add(propertyC);
}
}
In later code, after assigning propertyA and the other variables and trying to iterate over the List I get empty strings. I require the properties to be in the list. My questions is which would be the best way to achieve this?
Looks like you are getting empty strings because when you are adding to the list the values in your properties have not been set at the time that the Foo() constructor is called...
Try passing values and setting them in the Foo constructor as follows:
public class Foo{
public string propertyA;
public string propertyB;
public string propertyC;
public List<string> list;
Public Foo(string propA, string propB, string propC){
propertyA = propA;
propertyB = propB;
propertyC = propC;
list = new List<string>();
list.Add(propertyA);
list.Add(propertyB);
list.Add(propertyC);
}
}
Alternatively you could add the values to the list at a later time when the properties are actually set and not in the constructor e.g.
public string PropertyA
{
//set the person name
set { propertyA = value;
list.Add(value);
}
//get the person name
get { return propertyA; }
}
...
What you're seeing is expected behavior. Updating "propertyA", etc later on won't update the strings that have already been added to the collection.
You could consider using a Dictionary instead of your own class, and then adding and updating elements is easier: (and you don't have to keep updating your class with new property names)
var properties = new Dictionary<string, string>();
properties.Add("propertyA", "some value of property A");
properties["propertyA"] = "some new value";
And when you want to display the values later:
MessageBox.Show(string.Join(Environment.NewLine, properties));
Alternatively, if you want a class and the option of adding properties to it, then maybe extending the Dictionary class like this will at least make things easier to maintain, so you can add more properties that'll stay in sync with the underlying Dictionary, with a minimum of fuss.
public class PropertyCollection : Dictionary<string, string>
{
public string PropertyA
{
get { return GetValue(); }
set { StoreValue(value); }
}
public string PropertyB
{
get { return GetValue(); }
set { StoreValue(value); }
}
protected string GetValue([CallerMemberName] string propName = "")
{
if (ContainsKey(propName))
return this[propName];
return "";
}
protected void StoreValue(string propValue, [CallerMemberName] string propName = "")
{
if (ContainsKey(propName))
this[propName] = propValue;
else
Add(propName, propValue);
}
}
If you want to assign propertyA, B, C after an instance of Foo is created and enumerate them, you could try something like this:
public class Foo
{
public string propertyA { get { return list[0]; } set { list[0] = value; } }
public string propertyB { get { return list[1]; } set { list[1] = value; } }
public string propertyC { get { return list[2]; } set { list[2] = value; } }
public List<string> list = new List<string>() {"", "", ""};
}
For the reasons why the code behaves in a way you might not expect, see How are strings passed in .NET?
I'm developing a class which contains some const strings
public static class Constants
{
public const string CarID= "car_id";
//public const string NumberID= "number_id"; // this is the second const string might be added, so
//the new created function can return the two
}
public class CarENParameters
{
public string Params { get; set; }
public CarENParameters(string carId)
{
Params = carId;
}
}
public static class CarPropertyProcess
{
//test params
public static CarENProps Parse(Uri uri,string content)
{
string carID= Regex.Matches(content, #"\$\('#CarXL'\)\.val\((\d+)\)", RegexOptions.None)[0].Groups[1].Value;
var parameters = new Dictionary<string, string>
{
{Constants.CarID, carID},
};
return new CarENProps(uri.AbsoluteUri, parameters);
}
public static CarENParameters GetParameters()
{
return new CarENParameters(Constants.CarID);
}
}
In the class Constants, I have one carID, now the case is it might have more than one const string like : public const string NumberID= "number_id";
So I want to create one function to return a list of those const strings, which are car_id and number_id with a class name CarENParameters but I havent figured out how to return a list by a get/set in a class, should I use dictionary or keyvaluespair to achieve that ? I'm quite new to C# so hope that I can have a better point of view from the helps of you guys. Thanks
Are you looking for something like this:
public static List<CarENParameters> GetParameters()
{
return new List<CarENParameters>()
{
new CarENParameters(Constants.CarID1),
new CarENParameters(Constants.CarID2),
new CarENParameters(Constants.CarID3)
}
}
You can use reflection for this
don't forget to put using System.Reflection;
// get class type
Type type = typeof(Constants);
// get a list of fields
FieldInfo[] fields = type.GetFields();
List<CarENParameters> list = new List<CarENParameters>();
// loop on field list
foreach (FieldInfo field in fields)
{
// if field is a string add it to our return list
if (field.FieldType == typeof(String))
list.Add(new CarENParameters((String) field.GetValue(null)));
}
I seem to be having some trouble wrapping my head around the idea of a Generic List of Generic Lists in C#. I think the problem stems form the use of the <T> argument, which I have no prior experience playing with. Could someone provide a short example of declaring a class which is a List, that therein contains another List, but where the type of the object contained therein is not immediately known?
I've been reading through the MS documentation on Generics, and I am not immediately sure if I can declare a List<List<T>>, nor how exactly to pass the <T> parameter to the inside list.
Edit: Adding information
Would declaring a List<List<T>> be considered legal here? In case you are wondering, I am building a class that allows me to use a ulong as the indexer, and (hopefully) steps around the nasty 2GB limit of .Net by maintaining a List of Lists.
public class DynamicList64<T>
{
private List<List<T>> data = new List<List<T>>();
private ulong capacity = 0;
private const int maxnumberOfItemsPerList = Int32.MaxValue;
public DynamicList64()
{
data = new List<List<T>>();
}
A quick example:
List<List<string>> myList = new List<List<string>>();
myList.Add(new List<string> { "a", "b" });
myList.Add(new List<string> { "c", "d", "e" });
myList.Add(new List<string> { "qwerty", "asdf", "zxcv" });
myList.Add(new List<string> { "a", "b" });
// To iterate over it.
foreach (List<string> subList in myList)
{
foreach (string item in subList)
{
Console.WriteLine(item);
}
}
Is that what you were looking for? Or are you trying to create a new class that extends List<T> that has a member that is a `List'?
or this example, just to make it more visible:
public class CustomerListList : List<CustomerList> { }
public class CustomerList : List<Customer> { }
public class Customer
{
public int ID { get; set; }
public string SomethingWithText { get; set; }
}
and you can keep it going. to the infinity and beyond !
A list of lists would essentially represent a tree structure, where each branch would constitute the same type as its parent, and its leaf nodes would represent values.
Implementation
public sealed class TreeList<T> : List<TreeList<T>>
{
public List<T> Values { get; } = new List<T>();
public TreeList<T> this[int index]
{
get
{
while (index > Count - 1)
{
Branch();
}
return base[index];
}
}
public TreeList<T> Branch()
{
TreeList<T> result = new TreeList<T>();
Add(result);
return result;
}
}
Example
internal static class Program
{
public static void Main()
{
// Create the root element...
TreeList<string> treeList = new TreeList<string>();
// You can add branches the old-fashioned way...
treeList.Add(new TreeList<string>());
// Add leaf node values to your first branch...
treeList[0].Values.Add("Hello, World!");
treeList[0].Values.Add("Goodbye, World!");
// You can create new branches from any branch like this...
// Note: You could also chain branch statements; i.e. treeList.Branch().Branch().Branch()
TreeList<string> branch2 = treeList.Branch();
// Add leaf node values to your second branch...
branch2.Values.Add("Alice");
branch2.Values.Add("Bob");
// You can also create branches until you reach the desired branch index...
// The TreeList indexer will loop until the desired index has been created, and then return it.
treeList[7].Values.Add("Alpha");
treeList[7].Values.Add("Bravo");
treeList[7].Values.Add("Charlie");
// How many branches does the root have?
Console.WriteLine($"Treelist branches: {treeList.Count}");
// What's at branch 0's values?
foreach (string value in treeList[0].Values)
{
Console.WriteLine(value);
}
// What's at branch 1's values?
foreach (string value in treeList[1].Values)
{
Console.WriteLine(value);
}
// What's at branch 7's values?
foreach (string value in treeList[7].Values)
{
Console.WriteLine(value);
}
}
}
Now, whether you should implement something like this is another matter. Extending List<T> isn't recommended: Why not inherit from List<T>?
public class ListOfLists<T> : List<List<T>>
{
}
var myList = new ListOfLists<string>();
I have the following code
public class ChildClass
{
public string FieldName { get; set; }
public string Value { get; set; }
public string StatusClass { get; set; }
public string StatusMessage { get; set; }
}
Creating a list of list obj is as follows
List<List<ChildClass>> obj = new List<List<ChildClass>>();
Look a direct example here:
public partial class Form1 : Form
{
List<List<Label>> txtList;
List<List<int>> num;
public Form1()
{
InitializeComponent();
txtList = new List< List<Label> >() {
new List<Label> { label1, label2, label3 },
new List<Label> { label4, label5, label6 },
new List<Label> { label7, label8, label9 }
};
num = new List<List<int>>() { new List<int>() { 1, 2 }, new List<int>() { 3, 4 } };
}
}
you should not use Nested List in List.
List<List<T>>
is not legal, even if T were a defined type.
https://msdn.microsoft.com/en-us/library/ms182144.aspx
private List<string> _S3 = new List<string>();
public string S3[int index]
{
get
{
return _S3[index];
}
}
Only problem is I get 13 errors. I want to call string temp = S3[0]; and get the string value from the list with the particular index.
You can't do that in C# - you can't have named indexers like that in C#. You can either have a named property, with no parameters, or you can have an indexer with parameters but no name.
Of course you can have a property with a name which returns a value with an indexer. For example, for a read-only view, you could use:
private readonly List<string> _S3 = new List<string>();
// You'll need to initialize this in your constructor, as
// _S3View = new ReadOnlyCollection<string>(_S3);
private readonly ReadOnlyCollection<string> _S3View;
// TODO: Document that this is read-only, and the circumstances under
// which the underlying collection will change
public IList<string> S3
{
get { return _S3View; }
}
That way the underlying collection is still read-only from the public point of view, but you can access an element using:
string name = foo.S3[10];
You could create a new ReadOnlyCollection<string> on each access to S3, but that seems a little pointless.
C# cannot have parameters for their properties. (Side note: VB.Net can though.)
You can try using a function instead:
public string GetS3Value(int index) {
return _S3[index];
}
You have to use this notation
public class Foo
{
public int this[int index]
{
get
{
return 0;
}
set
{
// use index and value to set the value somewhere.
}
}
}
_S3[i] should automatically return the string at position i
So just do:
string temp = _S3[0];
Try this
private List<string> _S3 = new List<string>();
public List<string> S3
{
get
{
return _S3;
}
}
I would just go with
class S3: List<string>{}