How to use TreeView.Tag = object? - c#

Something like this:
Dictionary<int, string> myData = new Dictionary<int, string>();
myData.Add(1, "England");
myData.Add(2, "Canada");
myData.Add(3, "Australia");
myTreeView.Node[0].Tag = myData;
Then I want to get this object, how should I do it ?
Like:
string str = new string();
str = myTreeView.Node[0].Tag[2]; // "str" should be equal to "Canada"
myTreeView.Node[0].Tag[1] = "Spain";
str = myTreeView.Node[0].Tag[1]; // now "str" is equal to "Spain"
Second question - what will return this expression:
Dictionary<int, string> myData = new Dictionary<int, string>();
myData.Add(1, "England");
myData.Add(2, "Canada");
myData.Add(3, "Australia");
string str1 = new string();
str = myData[4]; // there isn't such a key as 4
Exception or null ?

Control.Tag is typed as object so you'll need to cast it to access it as a Dictionary<int, string>:
Dictionary<int, string> dict = (Dictionary<int, string>)myTreeView.Node[0].Tag;
string str = dict[2];
And similarly to set a value:
var dict = (Dictionary<int, string>)myTreeView.Node[0].Tag;
dict[1] = "Spain";
If you try to access a non-existent key, a KeyNotFoundException will be thrown. You can check if the dictionary contains a given key using TryGetValue or ContainsKey:
if(dict.ContainsKey(key))
{
var value = dict[key];
}
else
{
}
TryGetValue does the lookup and sets the given variable to the value (it it exists) in a single call, so is usually preferred.
string value;
if(dict.TryGetValue(key, out value))
{
//use value
}
else { ... }

Exception or null ?
Well, you could just try it out yourself or read the documentation (it throws an exception).
Also, your code will not compile as posted. Tag is a way to associate arbitrary data with an object. As a result, its type is object, so you will need to cast it before using it as you do.
If your code ever becomes unwieldy due to overuse of the Tag property I would suggest creating your own node type which inherits from the default TreeNode (or whatever it is) and populating your tree view with that type of object instead.

The tightest means for addressing the properties of a node tag is:
((TagType)node_identity.Tag).TagProperty = value;
Thus the tag properties of the parent node can be addressed so:
((TagType)node_identity.Parent.Tag).TagProperty = value;
The tag properties of a child node can be addressed so:
((TagType)node_identity.Nodes[index_of_child].Tag).TagProperty = value;
And as each Nodes[index_identifier] resolves to a node, the tag properties of more remote child nodes can be addressed so:
((TagType)node_identity.Nodes[index_of_child].Nodes[index_of_further_child].Tag).TagProperty = value;
Etc.
As far as the assumable objects of Tagging your dictionary are concerned... assuming your purposes require the same integer-string associations everywhere, I would instead simply store the integer key value to your Tag field, and pull the associated string from perhaps a global List<string> DictionaryStrings object. Then you could store only the integer index value to your Tags; and only the string values to your List<string>.
You would then read your Tag values as follows:
((int)node_identity.Tag)
Given these assumptions, you would instead populate your infrastructure so:
List<string> DictionaryStrings = new List<string>;
DictionaryStrings.Add("Canada"); // etc.
Then you would read the tag to pull your DictionaryString from the index value stored to your Tags as follows:
string DictionaryString = DictionaryStrings[((int)node_identity.Tag)];
Your error message is a consequence of addressing a prospective member of your dictionary which you have not yet added (at that execution point) to your dictionary. Fully populate the List or dictionary first; then only address valid indexes belonging to the List/dictionary.

Related

How to modify values of an object stored in a list

I have a class that is instantiated at the beginning of each iteration of a loop. Inside the loop, it's attributes need to be populated with the row values of a table returned by a stored procedure. As I have to iterate through each column of every row, in order to know which attribute of the class needs to be assigned a value and when, I have a dictionary that maps the column names to an index. This index refers to a position in a list that stores an attribute of an instance of the class:
while (reader.Read() && reader.HasRows)
{
Subscription subscription = new Subscription();
List<string> subscrData = new List<string>
{
subscription.attr1,
subscription.attr2,
subscription.attr3,
subscription.attr4
}
Dictionary<string, int> columnDict = new Dictionary<string, int>
{
{"attr1": 0},
{"attr2":1},
{"attr3":2},
{"attr4":3}
}
foreach (string colName in columnDict.Keys)
{
if (reader.GetSchemaTable().Columns[colName] == null)
subscrData[columnDict[colName]] = "null";
else
{
subscrData[columnDict[colName]] = reader[colName].ToString();
nullsReturned = false;
}
}
I'm probably coming at this from more of a C++ approach as with that you could store references to the class instance an modify its attributes, but this doesn't work with C# because lists store the values.
How can I restructure this code so that I can modify the actual attributes of the class instance while still being able to check if each column returned from the stored procedure is not null?
You don't need the list for this case. You either want to add a method like setAttribute(string attributeName) to your class (and within it build a switch/case to modify the given attribute); or, use reflection to change an instance field given its name.
I agree with Hasan. But just for your information: to implement your approach you could make use of Lambda expressions to keep track of the references to your properties (= the attributes).
Something like this would work:
Subscription subscription = new Subscription();
List<Expression<Func<Subscription, string>>> subscrData = new List<Expression<Func<Subscription, string>>>
{
a => a.attr1,
a => a.attr2,
a => a.attr3,
a => a.attr4,
};
//E.g. To update attribute 3 you can do this:
var prop = (PropertyInfo)((MemberExpression)subscrData[2].Body).Member;
prop.SetValue(subscription, "test string", null);

Get hashtable obj by key & change its public properties

First of all I declare a hashtable and its values. The key of a hashtable entry is a GUID and the value is an object with a few string values.
Guid g = Guid.NewGuid();
Hashtable hash = new Hashtable();
InstallationFiles instFiles = new InstallationFiles(string1, string2, string3);
hash.Add(g, instFiles);
//...add many other values with different GUIDs...
My goal is to give a user a possibility to EDIT string 1, string2, string3. To cut a long story short, I am in a position where I can get the "GUID g" of the entry which needs to be edited:
public void edit()
{
//here I retrieve the GUID g of the item which has to be edited:
object objectHash = item.Tag;
//here i loop through all hash entries to find the editable one:
foreach(DictionaryEntry de in hash)
{
if(de.Key.ToString() == objectHash)
{
//here I would like to access the selected entry and change string1 -
//the line below is not working.
hash[de.Key].string1 = "my new value";
}
}
}
How do I make this line work?
hash[de.Key].string1 = "my new value";
Use Dictionary<Guid, InstallationFiles> instead HashTable
upd. You can use this.
(hash[de.Key] as InstallationFiles).string1 = "asdasd"
Ok, explanation:
Because Hashtable is not generic type, it contains references on keys and values as Objects.
Thats why, when you access to your value hashtable[mykey], you got reference to Object. To make it as reference to your type (InstallationFiles), you have to from "reference to Object" get "reference to InstallationFiles". Im my sample I use "as" operator to do this.

How to get value from dictionary without knowing key?

I want to get value from dictionary but i don't know key(Because dynamic generate dictionary from database) how can i get dictionary value.
If you some idea share me ...
For Example my database string value like
string jsonString = " "FB": "[{\"title\":\"sheet1\",\"rows\":[{\"height\":\"undefined\",\"columns\":[{\"value\":\"Cover Group \"},{\"value\":\"Sample Variable\"},{\"value\":\"Coverpoint Name\"},{\"value\":\"Crossed cover points\"},{\"value\":\"Coverpoint Comment\"},{\"value\":\"Bin Type\"},{\"value\":\"Bin Id\"},{\"value\":\"Sample Value\"},{\"value\":\"Expected Bin Count\"},{\"value\":\"Set Max Bin\"},{\"value\":\"Not Used\"}]},{\"height\":\"undefined\",\"columns\":[{\"value\":\"allCg,allSi\"},{\"value\":\"exSingle\"},{\"value\":\"exSingle\"},{},{\"value\":\"Example for single bin\"},{\"value\":\"single\"},{\"value\":\"valZero\"},{\"value\":\"1'b0\"},{\"formula\":\"1\",\"value\":1},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{\"value\":\"single\"},{\"value\":\"valOne\"},{\"value\":\"1'b1\"},{\"formula\":\"1\",\"value\":1},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{\"value\":\"ex1Bus[3:0]\"},{\"value\":\"exMulti\"},{},{\"value\":\"Example for multibin\"},{\"value\":\"multi\"},{},{\"value\":\"[0:15]\"},{\"formula\":\"16\",\"value\":16},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{\"value\":\"exCross\"},{\"value\":\"exSingle,exMulti\"},{\"value\":\"Example for cross\"},{\"value\":\"Implicit\"},{},{},{\"formula\":\"32\",\"value\":32},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{\"value\":\"ex2Bus[15:0]\"},{\"value\":\"exWildcard\"},{},{\"value\":\"example for wildcard\"},{\"value\":\"wildcard\"},{\"value\":\"ex_wildcard\"},{\"value\":\"16'bxxxxxxxxxxxxxx1\"},{\"formula\":\"1\",\"value\":1},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{\"value\":\"ex3Bus[4:0]\"},{\"value\":\"exImplicit\"},{},{\"value\":\"example for implicit & set max bin\"},{\"value\":\"Implicit\"},{},{},{\"formula\":\"8\",\"value\":8},{\"formula\":\"8\",\"value\":8},{}]},{\"height\":\"undefined\",\"columns\":[{},{\"value\":\"ex4Bus[3:0]\"},{\"value\":\"ex4Bus\"},{},{\"value\":\"setup for ignore example\"},{\"value\":\"multi\"},{},{\"value\":\"[0:15]\"},{\"formula\":\"16\",\"value\":16},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{\"value\":\"exIgnore\"},{\"value\":\"exSingle,ex4Bus\"},{\"value\":\"example for ignore\"},{\"value\":\"ignore\"},{},{\"value\":\"ex4Bus([12:15])\"},{\"formula\":\"24\",\"value\":24},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{\"value\":\"ex5Bus[3:0]\"},{\"value\":\"exIllegal\"},{},{\"value\":\"example for illegal\"},{\"value\":\"illegal\"},{},{\"value\":\"[12:15]\"},{\"formula\":\"16\",\"value\":16},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{},{},{},{},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{},{},{},{},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{},{},{},{},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{},{},{},{},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{},{},{},{},{},{}]}],\"metadata\":{\"widths\":[\"200\",\"200\",\"200\",\"200\",\"200\",\"200\",\"200\",\"200\",\"200\",\"200\",\"200\"],\"frozenAt\":{\"row\":0,\"col\":0}}}]""
FB is dynamic key and after it's value title all value i need
If you don't have the key, but have the value and trying to get hold of the key, you can do this:
Dictionary<string, string> testData = new Dictionary<string, string>();
testData.Add("name", "Latheesan");
testData.Add("age", "26");
KeyValuePair<string, string> searchResult
= testData.FirstOrDefault(s => s.Value == "Latheesan");
string key = searchResult.Key; // returns "name" here
To get a sequence of all the Key/Value pairs where the value matches a target:
var dict = new Dictionary<string, int>
{
{"One", 1},
{"Two", 2},
{"Another One", 1},
{"Three", 3},
{"Yet Another One", 1}
};
int target = 1; // For example.
var matches = dict.Where(item => item.Value == target);
foreach (var kvp in matches)
Console.WriteLine("Key = " + kvp.Key);
The sample data you posted isn't a flat key-value dictionary. It contains embedded dictionaries - the base dictionary contains a title and a rows, which in turn consists of height and columns and so on, and at some point are key-value pairs who keys are, confusingly, named 'value'. Are you asking how to parse this data structure to get all the values whose key is value?
What you first need to do, since this appears to be a JSON-formatted entry, is parse the JSON into a .NET data structure, using libraries like JSON.NET or System.Web.Helpers.Json. These libraries will convert the JSON string into a hierarchy of dictionaries, all of them implementing IEnumerable, so you can iterate over it, more or less like this (this is not compilable code, just a demonstration!):
public void Main()
{
var jsonObject = Json.Decode(FB); // FB is your JSON string.
var values = new List<string>();
FindValues(jsonObject);
}
public void FindValues(jsonObject, values)
{
foreach (var child in jsonObject)
{
if (child.key == 'value')
{
values.Add(child.value);
}
// Recursively call FindValues on child objects.
FindValues(child, values);
}
}
This C#-ish pseudo-code shows you how to go over a dictionary, then optionally drill down deeper into internal dictionaries.
This code use for get value from dictionary value without knowing key and value..
var json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonString );
var javSer = new JavaScriptSerializer();
var dfi = javSer.Deserialize<Dictionary<string, string>>(json);
string dataString= dfi.Values.First();
How can you possibly know which value you need if you don't have the key?
A Dictionary in .NET does contain a Keys and Values collection, so if you are only interested in the values, you can use that.

How do I make a generated Object name?

How do I make a generated Object name? For example:
ObjectEx "name" = new ObjectEx();
Edit:
The object will be named by a user input.
The code will be:
Console.Write("Input new user's name: ");
string newUsersName = Console.ReadLine();
(Create ObjectEx)
Edit2:
I have a Dictionary for ObjectEx(Person) which handles all ObjectExs.
Person is the real class name, sorry about making the example object ObjectEx.
public static List<Person> persons = new List<Person>();
Objects don't have names - variables do, and they're always determined at compile-time.
If you want a map from string to object, just use a Dictionary<string, ObjectEx> - then come with random strings using Random. (There are plenty of examples of generating random strings on Stack Overflow.)
If you just want a collection of objects and you were using "random name" as a way of expressing that, use List<ObjectEx> - you don't need a name at all in that case.
If you need something else, please be more specific.
You can use array and store object in to that.
ObjectEx []arrObjectEx = new ObjectEx[10];
arrObjectEx[0] = new ObjectEx();
I would use list<T> (generic list) instead of array if the number of random elements are unknown.
List<ObjectEx> lstObjectEx = new List<ObjectEx>();
lstObjectEx.Add(new ObjectEx());
If randomly generated object need to be accessed uniquely then you can use dictionary. e.g
Dictionary<int, ObjectEx> dicObjectEx = new Dictionary<int, ObjectEx>();
dicObjectEx.Add(someUniqueNumber, new ObjectEx());
That is not possible but how about using a Dictionary. You can use a string value Add and Get hold of an Object you stored.
// somewhere near the start in your code initialize the dictionary
var dict = new Dictionary<string, Person>();
// later on you can dynamically add an Object to the Dictionary
// newUsersName is the so called Index
string newUsersName = Console.ReadLine();
dict.Add(newUsersName, new Person());
// if you need to get hold of that object again use the Index
// myObj is a Person type
var myObj = dict[newUsersName];
// assume Person has an Age property
myObj.Age = 20;
// show all Persons now in the dictionary
foreach(var username in dict.Keys)
{
Console.WriteLine(username);
var pers = dict[username];
Console.WriteLine("{0} is {1} years old", username, pers.Age );
}
You could use a dictionary to store objects, where the Key is the object name

Getting the property name that a value came from

I would like to know how to get the name of the property that a method parameter value came from. The code snippet below shows what I want to do:
Person peep = new Person();
Dictionary<object, string> mapping = new Dictionary<object, string>();
mapping[peep.FirstName] = "Name";
Dictionary<string, string> propertyToStringMapping = Convert(mapping);
if (mapping[peep.FirstName] == propertyToStringMapping["FirstName"])
Console.WriteLine("This is my desired result");
private Dictionary<string, string> Convert(Dictionary<object, string> mapping)
{
Dictionary<string, string> stringMapping = new Dictionary<string, string>();
foreach (KeyValuePair<object, string> kvp in mapping)
{
//propertyName should eqal "FirstName"
string propertyName = kvp.Key??????
stringMapping[propertyName] = kvp.Value;
}
return stringMapping;
}
You are not able to do so in this way, since the way it works is that C# evaluates the value of FirstName property by calling its get accessor and passes the value of that to the indexer of the dictionary. Therefore, the way you found out FirstName value is completely lost. Just like the way you evaluate 2 + 2.
If you write, "x = 2 + 2", x will have the value 4 but there will be no way to tell if it was 3 + 1 or 2 + 2 or 5 + (-1) or ... that evaluated to 4.
I think ultimately you will need to store either the PropertyInfo object associated with the property, or the string representation of the property name in you mapping object. The syntax you have:
mapping[peep.FirstName] = "Name";
Would create an entry in the dictionary with a key value equal to the value of the peep.FirstName property, and the Value equal to "Name".
If you store the property name as a string like:
mapping["FirstName"] = "Name";
You could then use reflection to get the "FirstName" property of your object. You would have to pass the "peep" object into the Convert function, however. This seems to be somewhat opposite of what you are wanting to do.
You may also be able to get crazy with Expressions and do something like:
var mapping = new Dictionary<Expression<Action<T>>,string>();
mapping[ p => p.FirstName ] = "Name";
Then in your Convert function you could examine the expression. It would look something like:
private Dictionary<string,string> Convert(Dictionary<Expression<Action<T>>,string> mapping)
{
var result = new Dictionary<string,string>();
foreach(var item in mapping)
{
LambdaExpression ex = item.Key as LambdaExpression;
string propertyName = ((MemberExpression)ex.Body).Member.Name;
string propertyValue = item.Value;
result.Add(propertyName,proeprtyValue);
}
return result;
}
This is more or less off the top of my head, so I may have the expression types off a bit. If there are issues with this implementation let me know and I will see if I can work out a functional example.
I don't know much about C#, but I suppose peep is an enum? As for Java, you could do:
String propertyName = kvp.key.toString()
Maybe there's something similar in C#?
And even if peep isn't a enum: I see no reason why the key should be an arbitrary object? So maybe the solution is exactly to use an enum as type of the key?
Also, I don't know what you're trying to do but usually, I'd not recommend you to convert the enum key to a string. What can you do with a string what you can't do, too, with an enum?

Categories

Resources