I have the List<ValuePair> object: listUserRoleValuePair. I have to add ixUser and name as my value pair in the list in foreach loop. How I can Add this?
List<ValuePair> listUserRoleValuePair = new List<ValuePair>();
var ixUserList= _mapper1.FindUserRoleLike(sName);
User result = null;
foreach (var ixUser in ixUserList)
{
result = new UserMapper(connection).FindById(ixUser);
var name = result.SFirstName + " " + result.SLastName;
//listUserRoleValuePair.Add(ixUser);
// listUserRoleValuePair.Add(
}
my ValuePair class is as below
public class ValuePair
{
private string _index;
private string _sName;
public ValuePair(string index, string sName)
{
_index = index;
_sName = sName;
}
public string Index
{
get { return _index; }
set { _index = value; }
}
public string SName
{
get { return _sName; }
set { _sName = value; }
}
}
You can use the KeyValuePair class:
List<KeyValuePair<string,string>> listUserRoleValuePair = new List<KeyValuePair<string,string>>();
And then:
listUserRoleValuePair.Add(new KeyValuePair<string,string>(name, ixUser);
You can also use a Dictionary instead of a List.
Provided ixUser is the index string, use this code:
List<ValuePair> listUserRoleValuePair = new List<ValuePair>();
var ixUserList= _mapper1.FindUserRoleLike(sName);
User result = null;
foreach (var ixUser in ixUserList)
{
result = new UserMapper(connection).FindById(ixUser);
var name = result.SFirstName + " " + result.SLastName;
listUserRoleValuePair.Add(new ValuePair(ixUser, name));
}
listUserRoleValuePair.Add(new ValuePair(index, name));
Im, not clear what the index value is for your objects, but whatever it is, just replace it in the line above
you can add only items that support the child object type in your case you can use one of these.
collection.Add(new ValuePair(index, Name))
or
collection.Add(new ValuePair(){Index = index,SName= Name});
or very simple create object and pass as
Valuepair valpair = new ValuePair();
valpair.Index = index;
valpair.SName = name;
collection.Add(valpair);
Try this
var pair = new ValuePair();
// somehow intialize pair
listUserRoleValuePair.Add(pair);
listUserRoleValuePair.Add(new ValuePair(ixUser, name));
Related
I have the following list of strings :
var files = new List<string> {"file0","file1","file2","file3" };
I would like to be able to add new files to this list, but if the inserted file is present in the list, I would like to insert custom value that will respect the following format $"{StringToBeInserted}"("{SomeCounter}
For instance : try to add "file0" and "file0" is already I would like to insert "file0(1)". If I try again to add "file0" ... I would like to insert with "file0(2)" and so on ... Also, I would like to provide a consistency, for instance if I delete "file0(1)" ... and try to add again "item0" ... I expect that "item0(1)" to be added. Can someone help me with a generic algorithm ?
I would use a HashSet<string> in this case:
var files = new HashSet<string> { "file0", "file1", "file2", "file3" };
string originalFile = "file0";
string file = originalFile;
int counter = 0;
while (!files.Add(file))
{
file = $"{originalFile}({++counter})";
}
If you have to use a list and the result should also be one, you can still use my set approach. Just initialize it with your list and the result list you'll get with files.ToList().
Well, you should create your own custom class for it, using the data structure you described and a simple class that includes a counter and an output method.
void Main()
{
var items = new ItemCountList();
items.AddItem("item0");
items.AddItem("item1");
items.AddItem("item2");
items.AddItem("item0");
items.ShowItems();
}
public class ItemCountList {
private List<SimpleItem> itemList;
public ItemCountList() {
itemList = new List<SimpleItem>();
}
public void DeleteItem(string value) {
var item = itemList.FirstOrDefault(b => b.Value == value);
if (item != null) {
item.Count--;
if (item.Count == 0)
itemList.Remove(item);
}
}
public void AddItem(string value) {
var item = itemList.FirstOrDefault(b => b.Value == value);
if (item != null)
item.Count++;
else
itemList.Add(new SimpleItem {
Value = value,
Count = 1
});
}
public void ShowItems() {
foreach (var a in itemList) {
Console.WriteLine(a.Value + "(" + a.Count + ")");
}
}
}
public class SimpleItem {
public int Count {get; set;}
public string Value {get; set;}
}
I'm trying to add objects of DataPerLabel to my Arraylist allData, following the code of DataPerLabel:
class DataPerLabel
{
public String labelName;
public String labelAdress;
public String dataType;
public DataPerLabel(String labelName, String labelAdress, String dataType)
{
this.labelName = labelName;
this.labelAdress = labelAdress;
this.dataType = dataType;
}
public String getLabelName()
{
return labelName;
}
public String getLabelAdress()
{
return labelAdress;
}
public String getDataType()
{
return dataType;
}
}
In the following code I try to add the objects of DataPerLabel to my arraylist:
submitButton.Click += (sender, args) =>
{
String label = textboxLabel.Text;
String adress = textboxAdress.Text;
String dataType = "hey";
if (buttonsLabelBool.Checked)
{
dataType = "Bool";
}
else if (buttonsLabelReal.Checked)
{
dataType = "Real";
}
else if (buttonsLabelInt.Checked)
{
dataType = "Int";
}
allData.Add(new DataPerLabel(label, adress, dataType));
};
And finally I try to read out the arrayList by displaying it in a textbox, see the following code:
private void test()
{
Button btn = new Button();
btn.Location = new Point(500,500);
btn.Text = "test";
btn.Click += (sender, args) =>
{
foreach (var item in allData)
{
//Display arraylist per object here
//Something like : item.getLabelName();
}
};
}
I'm not sure what I'm doing wrong, hope you can help!
ArrayList stores a list of System.Object. You need to cast the object back to DataPerLabel as follows:
foreach (var item in allData)
{
((DataPerLabel)item).getLabelName();
}
Alternatively, you could specify the data type in the foreach instead of var as Jakub Dąbek pointed out in the comment as follows:
foreach (DataPerLabel item in allData)
{
item.getLabelName();
}
A better approach would be to use generic list/collection List<DataPerLabel> to store the data so that the casting can be avoided.
Yiu should use a List<T> instead of ArrayList. This way every item in your list has the right type already and you can access the members:
foreach (DataPerLabel item in allData)
{
item.GetLabelItem();
}
This assumes allData is defined like this:
allData = new List<DataPerLabel>();
instead of allData = new ArrayList()
If you really have to use an ArrayList than you should cast your item to the actual type. The code above actually does this allready. However you could also use this:
foreach (var item in allData)
{
((DataPerLabel)item).GetLabelItem();
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to clean up my class using reflection.
private List<String> centers = new List<String>();
private List<String> leftWingers = new List<String>();
private List<String> rightWingers = new List<String>();
private List<String> defencemen = new List<String>();
private List<String> goalies = new List<String>();
private List<String> bench = new List<String>();
public List<String> Centers { get { return centers; } set { centers = value; } }
public List<String> LeftWingers { get { return leftWingers; } set { leftWingers = value; } }
public List<String> RightWingers { get { return rightWingers; } set { rightWingers = value; } }
public List<String> Defencemen { get { return defencemen; } set { defencemen = value; } }
public List<String> Goalies { get { return goalies; } set { goalies = value; } }
public List<String> Bench { get { return bench; } set { bench = value; } }
public String ToString()
{
String output = "";
System.Reflection.PropertyInfo[] properties = this.GetType().GetProperties();
foreach (System.Reflection.PropertyInfo property in properties)
{
int count = 0;
foreach (String value in property)
{
count++;
output += "C" + count + ": " + value + System.Environment.NewLine;
}
}
}
This will not work. I cant seem to be able to loop over items of each property because they are collections. Is there a way to get the contents of the String Lists from the PropertyInfo object?
They are not properties, they are fields,so you need to use GetFields
You need to tell GetFields method that you want to get private
members using BindingFlags, otherwise it will look for public and instance members by default.
var fields = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
Well, if you really want properties, the first thing is that you do not have properties on your code. You have just some attributes. Change it for properties if it is the case, for sample:
private List<String> centers { get; set; }
private List<String> leftWingers { get; set; }
private List<String> rightWingers { get; set; }
private List<String> defencemen { get; set; }
private List<String> goalies { get; set; }
private List<String> bench { get; set; }
Then you could read them as collections and read values, for sample:
public String ToString()
{
StringBuilder output = new StringBuilder();
System.Reflection.PropertyInfo[] properties = this.GetType().GetProperties();
foreach (System.Reflection.PropertyInfo property in properties)
{
var values = property.GetValue(this, null) as IEnumerable<String>;
if (values != null)
{
int count = 0;
foreach (String value in values)
{
count++;
output.AppendLine(string.Format("C{0}: {1}", count, value));
}
}
}
return output.ToString();
}
Another case is to read the fields and avoid converting it to properties. Look the Selman22's answer!
Your problem can be drastically simplified using Enumerable.Concat, Enumerable.Select and string.Join:
IEnumerable<string> allItems = centers.Concat(leftWingers)
.Concat(rightWingers)
.Concat(defencemen)
.Concat(goalies)
.Concat(bench);
return string.Join
(
Environment.NewLine,
allItems.Select((item, index) => $"C {index + 1}: {item}")
);
These are fields, so you need to use GetFields to obtain them. Please note also that fields returned by reflection are just metadata, they don't contain the data that you need.
To get the data, you need to use the GetValue method to get the field value for the current object.
Then, to be able to enumerate the collection in the field, you need to cast it as IEnumerable<string>.
Here is how it would look like:
public String ToString()
{
String output = "";
var fields = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var field in fields)
{
int count = 0;
foreach (String value in (IEnumerable<string>) field.GetValue(this))
{
count++;
output += "C" + count + ": " + value + System.Environment.NewLine;
}
}
return output;
}
Since you have only 6 collections, you can have a solution that does not involve reflection. Here is an example:
public String ToString()
{
String output = "";
var collections = new[] {centers, leftWingers, rightWingers, defencemen, goalies, bench};
foreach (var field in collections)
{
int count = 0;
foreach (String value in field)
{
count++;
output += "C" + count + ": " + value + System.Environment.NewLine;
}
}
return output;
}
Please consider using a StringBuilder instead of a string. Using a string to concatenate strings will hurt performance.
I want to learn classes atm and here is what I came up with:
Class level to create a level. This class has an object array that fills itself with rooms (raeume) which is the other class. Now, I want to access the objects in the object array from room, after I inserted them. Here is what I want to type:
wohnung.rooms[i].raumname.toString();
Here are the two classes
class raum
{
static object[] o_nebenraum = new object[3]; //N-O-S-W
static string s_raumname = "";
public object[] nebenraume
{
get
{
return o_nebenraum;
}
set
{
o_nebenraum = value;
}
}
public string raumname
{
get
{
return s_raumname;
}
set
{
s_raumname = value;
}
}
}
class level
{
static object[] o_rooms = new object[100];
public object[] rooms
{
get
{
return o_rooms;
}
set
{
o_rooms = value;
}
}
}
Here is how I set everything up.
level wohnung = new level();
raum keller = new raum();
raum wohnzimmer = new raum();
raum kueche = new raum();
raum schlafzimmer = new raum();
wohnung.rooms[0] = keller;
wohnung.rooms[1] = wohnzimmer;
wohnung.rooms[2] = kueche;
wohnung.rooms[3] = schlafzimmer;
keller.raumname = "Keller";
wohnzimmer.raumname = "Wohnzimmer";
kueche.raumname = "Küche";
schlafzimmer.raumname = "Schlafzimmer";
for (uint i = 0; i < 3; i++)
{
Console.WriteLine("Wohnung beinhaltet jetzt " + *MISSING CODE PART, I WANT TO GET THE .raumname out of the object array from wohnung.room*);
}
Console.ReadKey();
You have to use generic typed list List<T> (See on MSDN) instead of array, in this case you'll have the indexed access for the typed list elements
So instead of:
static object[] o_rooms = new object[100];
public object[] rooms
Use:
static IList<raum> o_rooms = new List<Raum>(100);
public IList<raum> rooms
Try this(in the for Loop):
Console.WriteLine("Wohnung beinhaltet jetzt " + (wohnung.rooms[i] as raum).raumname );
You would be better off using generics though in which case the class level would now look like:
class level
{
static List<raum> o_rooms = new List<raum>();
public List<raum> rooms
{
get { return o_rooms; }
set { o_rooms = value; }
}
}
and the for loop can be replaced with a foreach loop as follows:
foreach(raum room in wohnung.rooms)
{
Console.WriteLine("Wohnung beinhaltet jetzt " + room.raumname );
}
I have a method called get Data which executes my SQL and returns some rows of ContactLists containing Aggregated Labels.At the moment this method is in my code behind and would like to move it to a separate Data Access class. I would appreciate your assistance. Thanks!
Is normal, if i understand your code, you do this operation after ContactList initialization:
contactList.Labels = new ObservableCollection<Label>()
{
new Label() {
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
};
For each ContactList is always added one item, you will do something like this:
contactList.Labels = new ObservableCollection<Label>();
foreach(var item in <yourLabelDataSource>)
contactList.Labels.Add(new Label(...));
The solution is like this:
Dictionary<int, ContactList> myContactDictionary = new Dictionary<int, ContactList>();
using (DB2DataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
int id = Convert.ToInt32(dr["CONTACT_LIST_ID"]);
if (!myContactDictionary.ContainsKey(id))
{
ContactList contactList = new ContactList();
contactList.ContactListID = id;
contactList.ContactListName = dr["CONTACT_LIST_NAME"].ToString();
contactList.Labels = new ObservableCollection<Label>()
{
new Label()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
};
myContactDictionary.Add(id, contactList);
}
else
{
//Add new label because CONTACT_LIST_ID Exists
ContactList contactList = myContactDictionary[id];
contactList.Labels.Add(
new Label()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
);
}
}
}
Ben, for your last question you can use this solution:
else
{
//Add new label because CONTACT_LIST_ID Exists
ContactList contactList = myContactDictionary[id];
string name = dr["LABEL_NAME"].ToString();
var label = contactList.Labels.Where(l => l.Name == name).FirstOrDefault();
if( label != null )
label.Count += Convert.ToInt32(dr["LABEL_COUNT"]);
else
{
contactList.Labels.Add(
new Label()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
);
}
I hope this code is readable and helpfulL!
}
This is other response:
Create and Object Model that can contain your required data:
public class DataResult
{
public ObservableCollection<AggregatedLabel> AggregatedLabels { get; set; }
public ObservableCollection<ContactList> ContactLists { get; set; }
}
You can build a method that return DataResult object, in your method (GetData()), you can valorize the two different properties (AggregatedLabels and ContactsList) with your DB Result. In the and you can return DataResult Object.
A little example here:
public DataResult GetData()
{
DataResult result = new DataResult();
result.AggregatedLabels = new ObservableCollection<AggregatedLabel>();
result.ContactLists = new ObservableCollection<ContactList>();
// Manipulate data result with your method logic like in this examle:
foreach(var something in dbResult)
{
ContactList cl = new ContactList() {
//Binding from something
}
result.ContactLists.Add(cl);
}
return result; //return your Object Model with required Data!
}
I hope it is conceptually clear