Passing image into Android ListView ArrayAdapter - c#

I have a ListView and I am passing value to this list using ArrayAdapter.
This is what I did.
first I created string array:
private static readonly string[] menuItemNames = new string[] {
"Home", "New", "Delete", "Submit", "Help"
};
And then created ArrayAdapter:
this.MyMenuList.Adapter = new ArrayAdapter<string> (this, Resource.Layout.item_menu, Resource.Id.MenuItemText, menuItemNames);
And this seems to work fine. The values from menuItemNames array goes into the list and makes a new item. But next to each item, I have an icon.
How Can I set the icon of each one?
This is what I tried:
Drawable sideIcon1 = context.Resources.GetDrawable (Resource.Drawable.home_icon);
Drawable sideIcon2 = context.Resources.GetDrawable (Resource.Drawable.new_icon);
Drawable sideIcon3 = context.Resources.GetDrawable (Resource.Drawable.delete_icon);
Drawable sideIcon4 = context.Resources.GetDrawable (Resource.Drawable.submit_icon);
Drawable sideIcon5 = context.Resources.GetDrawable (Resource.Drawable.help_icon);
Then, made drawable array:
Drawable[] sideMenuItemIconsDrawables = new Drawable[] {
sideIcon1, sideIcon2, sideIcon3, sideIcon4, sideIcon5
};
And then make a new ArrayAdapter:
this.MyMenuList.Adapter = new ArrayAdapter<Drawable> (this, Resource.Layout.item_menu, Resource.Id.ImgView, sideMenuItemIconsDrawables);
This doesn't seem to work.
What do I nee to pass instead of drawable to change the image of that ImageView ?
Thank you for your time.
// ===========================================================
EDIT:
So this is what I tried. But it crashes my app before even the view loads.
The adapter count changes but it just crashes after that.
IList<IDictionary<string, object>> menuItemNames = new List<IDictionary<string, object>> ();
Dictionary<string, object> sideItem1 = new Dictionary<string, object> ();
sideItem1.Add ("text", "SideMenuItem1");
sideItem1.Add ("icon", Resource.Drawable.menu_Icon);
Dictionary<string, object> sideItem2 = new Dictionary<string, object> ();
sideItem2.Add ("text", "SideMenuItem2");
sideItem2.Add ("icon", Resource.Drawable.back_arrow_box);
Dictionary<string, object> sideItem3 = new Dictionary<string, object> ();
sideItem3.Add ("text", "SideMenuItem3");
sideItem3.Add ("icon", Resource.Drawable.bar_addAbsence);
Dictionary<string, object> sideItem4 = new Dictionary<string, object> ();
sideItem4.Add ("text", "SideMenuItem4");
sideItem4.Add ("icon", Resource.Drawable.bar_addExpense);
Dictionary<string, object> sideItem5 = new Dictionary<string, object> ();
sideItem5.Add ("text", "SideMenuItem5");
sideItem5.Add ("icon", Resource.Drawable.bar_addTime);
menuItemNames.Add (sideItem1);
menuItemNames.Add (sideItem2);
menuItemNames.Add (sideItem3);
menuItemNames.Add (sideItem4);
menuItemNames.Add (sideItem5);
string[] sideMenuFromArr = { "text", "icon" };
int[] sideMenuToArr = { Resource.Id.textSideMenuItem, Resource.Id.imgViewSideMenuItemIcon };
SimpleAdapter sideMenuListAdapter = new SimpleAdapter (context, menuItemNames, Resource.Layout.item_menu, sideMenuFromArr, sideMenuToArr);
this.absHomeSideMenuList.Adapter = sideMenuListAdapter;

There are several ways of solving that, to me I think using SimpleAdapter is the simplest way. Make a List of HashMap of string and object. Create your layout, populate your List with the text and icons you wish to use and pass the layout and List to your SimpleAdapter constructor.
Something like:
List<HashMap<String, Object>> menuItemNames = new ArrayList<HashMap<String,Object>>();
HashMap<String, Object> row = new HashMap<String, Object>();
row.put("icon", R.drawable.home_icon);
row.put("text", "Home");
menuItemNames.add(row);
row = new HashMap<String, Object>();
row.put("icon", android.R.drawable.new_icon);
row.put("text", "New");
menuItemNames.add(row);
row = new HashMap<String, Object>();
row.put("icon", android.R.drawable.delete_icon);
row.put("text", "Delete");
menuItemNames.add(row);
int[] to = {R.id.sideMenuItemIconsDrawables, R.id.MenuItemText}; //IDs of your text and icon
String[] from = {"icon", "text"};
adapter = new SimpleAdapter(this, menuItemNames, R.layout.item_menu, from, to);
listView.setAdapter(adapter);
I hope this helps.

Related

List<KeyValuePair> overrides added values

I am currently facing an issue where I want to add different values to the same Key in a foreach loop.
List<KeyValuePair<string, Dictionary<string, string>>> sysList = new List<KeyValuePair<string, Dictionary<string, string>>>();
Dictionary<string, string> newSystem = new Dictionary<string, string>();
string line1="";
string line2="";
string quit="";
foreach(Worksheet ws in workbook.Worksheets)
{
while(quit != q)
{
newSystem.Clear();
line1 = Console.ReadLine();
line2 = Console.ReadLine();
quit = Console.ReadLine();
}
newSystem.Add(line1, line2);
sysList.Add(new KeyValuePair<string, Dictionary<string, string>>(ws.Name,newSystem));
}
For the first iteration (within while) of the first Worksheet ws everything is fine. If the I choose to do >1 iterations within this Worksheet, there is a new entry added, but the Dictionary values are all the same, f.e.:
syList[0]: "worksheetName","test1","test2"
syList[1]: "worksheetName","test1","test2"
syList[2]: "worksheetName","test1","test2"
If there are several foreach iterations, the names stay the same, but the Dictionary Key and Values added by newSys are the same [AFTER the second foreach iteration]:
syList[0]: "worksheetName1","test1","test2"
syList[1]: "worksheetName1","test1","test2"
syList[2]: "worksheetName1","test1","test2"
syList[3]: "worksheetName2","test1","test2"
syList[4]: "worksheetName2","test1","test2"
Initially I tried using Dictionaries, but could not handle the same keys properly and did not find a proper solution except for using List.
I am very grateful for any help provided.
If there are additional details that you require, please, let me know.
Edit:
desired result (example):
#########: ws.Name, line1, line2
syList[0]: "worksheetName1","ABC","1"
syList[1]: "worksheetName1","DEF","2"
syList[2]: "worksheetName1","ABC","5"
syList[3]: "worksheetName2","ABD","4"
syList[4]: "worksheetName2","ZZZ","1"
In case you don't want to maintain any uniqueness in the keys and just want a flat list, you can use the C#7 tuple syntax to build your list.
List<string> sheetNames = new List<string>() { "worksheetName1", "worksheetName2" };
var sysList = new List<(string SheetName, string line1, string line2)>();
string line1 = string.Empty;
string line2 = string.Empty;
string quit = string.Empty;
foreach (var sheet in sheetNames)
{
while (quit != "E")
{
line1 = Console.ReadLine();
line2 = Console.ReadLine();
quit = Console.ReadLine();
sysList.Add((sheet, line1, line2));
}
quit = string.Empty;
}
Try code below :
List<List<string>> syList = new List<List<string>>() {
new List<string>() {"worksheetName1","test1","test2"},
new List<string>() {"worksheetName1","test1","test2"},
new List<string>() {"worksheetName1","test1","test2"},
new List<string>() {"worksheetName2","test1","test2"},
new List<string>() {"worksheetName2","test1","test2"}
};
Dictionary<string, Dictionary<string, List<string>>> dict = syList
.GroupBy(x => x.First(), y => y)
.ToDictionary(x => x.Key, y => y
.GroupBy(a => a.Skip(1).FirstOrDefault(), b => b.Last())
.ToDictionary(a => a.Key, b => b.ToList()));
//using normal looping
Dictionary<string, Dictionary<string, List<string>>> dict2 = new Dictionary<string, Dictionary<string, List<string>>>();
foreach (List<string> sy in syList)
{
if (dict2.ContainsKey(sy[0]))
{
Dictionary<string, List<string>> tempDict = dict2[sy[0]];
if (tempDict.ContainsKey(sy[1]))
{
tempDict[sy[1]].Add(sy[2]);
}
else
{
List<string> newList = new List<string>() { sy[2] };
tempDict.Add(sy[1], newList);
}
}
else
{
Dictionary<string, List<string>> newDict = new Dictionary<string, List<string>>();
newDict.Add(sy[1], new List<string> { sy[2] });
dict2.Add(sy[0], newDict);
}
}

Create data.table using RDotNet

I'm trying to convert some R code script into C# code via RDotNet Library.
I was able to convert a big part but there's an issue while creating data.table in C#.
Above is my code example:
Dictionary<string, List<string>> myDic = new Dictionary<string, List<string>>();
// populate the dictionary
var colNames = new List<string>() { "col1", "col2"};
IEnumerable[] columns = new IEnumerable[2];
columns[0] = myDic.Keys;
columns[1] = myDic.Values;
var mydata = engine.CreateDataFrame(columns.ToArray(), colNames.ToArray(), stringsAsFactors: false);
when i use the variable mydata, I got an exception
Cannot convert type System.Collections.Generic.List`1[System.String][] to an R vector
Are you sure you want to create a dataframe column that contains a list of strings in each cell? It's not how you create a dataframe in R. The code below works when you replace Dictionary<string,List<string>> with Dictionary<string,string>.
Dictionary<string, string> myDic = new Dictionary<string, string>() {
{ "a","aaaa"},
{ "b","bbbb"},
{ "c","cccc"}
};
// populate the dictionary
var colNames = new List<string>() { "col1", "col2" };
IEnumerable[] columns = new IEnumerable[2];
columns[0] = myDic.Keys.ToArray();
columns[1] = myDic.Values.ToArray();
REngine engine = REngine.GetInstance();
var mydata = engine.CreateDataFrame(columns, colNames.ToArray(), stringsAsFactors: false);

Method name expected

I have to create a json file with an array inside in c# so this is my code but throws an exception:
Method name expected
before new Dictionary<string, int>[2]();
Have you got any suggestions?
int[] lung = results.ToArray();
Dictionary<string, Dictionary<string, int>[]> padre = new Dictionary<string, Dictionary<string, int>[]>();
Dictionary<string, int>[] udemy = new Dictionary<string, int>[2]();
padre.Add("Lunghezza", udemy);
udemy[0].Add("attributo", lung[0]);
udemy[1].Add("attributo2", lung[1]);
string js = JsonConvert.SerializeObject(padre);
System.Diagnostics.Debug.WriteLine(js);
This isn't how you construct an array;
new Dictionary<string, int>[2]()
You don't need the () at all - you're not calling a method or a constructor; you're creating an array instance. Just:
new Dictionary<string, int>[2]
You'll need to populate the array as well, of course, e.g.
udemy[0] = new Dictionary<string, int>();
udemy[1] = new Dictionary<string, int>();
Using a simpler array type makes it easier to see the problem:
// Invalid
int[] x = new int[2]();
// Valid
int[] x = new int[2];
As a side note, a type of Dictionary<string, Dictionary<string, int>[]> is pretty horrible - I would strongly encourage you to redesign that to use more meaningful types.
int[] lung = results.ToArray();
Dictionary<string, Dictionary<string, int>[]> padre = new Dictionary<string, Dictionary<string, int>[]>();
Dictionary<string, int>[] udemy = new Dictionary<string, int>[2]();
// populate
udemy[0].Add("attributo", lung[0]);
udemy[1].Add("attributo2", lung[1]);
// then add
padre.Add("Lunghezza", udemy);
string js = JsonConvert.SerializeObject(padre);
System.Diagnostics.Debug.WriteLine(js);

How to create and populate a nested dictionary with three keys

I have a unique double corresponding to a variation of three strings. I want to populate a dictionary or something such that I can call something like dict[key1][key2][key3] and get the value.
I've tried a whole bunch of things like
Dictionary<string, Dictionary<string, double>> dict = new Dictionary<string, Dictionary<string, double>> {
{ "Foo", {"Bar", 1.2 } },
{ "Foo", {"Test", 3.4 } }
};
Which gives me syntax errors and errors like "Error 4 A namespace cannot directly contain members such as fields or methods"
And
Dictionary<double, Tuple<string, string>> dict = {
{1.23, "Blah", "Foo"}
};
Which gives me errors like "Error 1 Can only use array initializer expressions to assign to array types. Try using a new expression instead."
And
object dict = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
dict["k1"] = new Dictionary<string, Dictionary<string, string>>();
dict["k1"]["k2"] = new Dictionary<string, string>();
dict["k1"]["k2"]["k3"] = 3.5;
Which gives me syntax errors and errors like "Error 2 Invalid token '"k1"' in class, struct, or interface member declaration"
How should I go about this? Thanks in advance.
![enter image description here][1]
Edit: Trying Jonesy's code:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
string[] grades = { "Grade 1", "Grade 5", "Grade 8", "ASTM A325", "316 Stainless", "Monel", "Brighton Best 1960" };
string[] sizes = { "#1", "2", "3", "4", "5", "6", "8", "10", "12", "1/4", "5/16", "3/8", "7/16", "1/2", "9/16", "5/8", "3/4", "7/8", "1", "1-1/8", "1-1/4", "1-3/8", "1-1/2" };
var dict = new Dictionary<string, Dictionary<string, Dictionary<string, double>>>();
dict["k1"] = new Dictionary<string, Dictionary<string, double>>();
dict["k1"]["k2"] = new Dictionary<string, double>();
dict["k1"]["k2"]["k3"] = 3.5;
public Form1()
{
InitializeComponent();
}
your last attempt is close, you want:
var dict = new Dictionary<string, Dictionary<string, Dictionary<string, double>>>();
dict["k1"] = new Dictionary<string, Dictionary<string, double>>();
dict["k1"]["k2"] = new Dictionary<string, double>();
dict["k1"]["k2"]["k3"] = 3.5;
you want var instead of object
(or Dictionary<string, Dictionary<string, Dictionary<string, double>>> if you like scrolling)
and your very last string should be a double.
As I understood, you have data and want to perform lookup in it. Why can't you just use some database for that purpose?
But if you really want to hardcode all values, you can. Just don't initialize dictionary manually, make simplifications - parse data in runtime.
Something like this. (I suppose, that you are novice in c# programming, so I've created new Console Application and copy-pasted all the code for your convenience)
public class Program
{
// harcode all data as string
const string RawData =
"k11,k12,k13=3.4;" +
"k21,k22,k23=4.42;" +
"k31,k32,k33=5.91;" +
"k41,k42,k43=8.14;" +
"k51,k52,k53=4.13;" +
"k61,k62,k63=5.4";
static void Main(string[] args)
{
// create dictionary from hardcoded string
var data = ParseData();
// use Tuple as key for data lookup
var value = data[Tuple.Create("k11", "k12", "k13")];
// check, that value equals expected one
Debug.Assert(value == 3.4);
}
private static IDictionary<Tuple<string, string, string>, double> ParseData()
{
var parsedData =
RawData
.Split(';')
.Select(ParseRow)
.ToDictionary(x => x.Item1, x => x.Item2);
return parsedData;
}
private static Tuple<Tuple<string, string, string>, double> ParseRow(string row)
{
var parts = row.Split('=');
var coefficients = ParseCoefficients(parts[0]);
var value = Double.Parse(parts[1], CultureInfo.InvariantCulture);
return Tuple.Create(coefficients, value);
}
private static Tuple<string, string, string> ParseCoefficients(string row)
{
var coeffs = row.Split(',');
var result = Tuple.Create(coeffs[0], coeffs[1], coeffs[2]);
return result;
}
}
As another simplification, you can use custom class as dictionary key instead of nested dictionaries. Write your own(pay attention, that it should override equality members Equals and GetHashCode), or use something from base class library. Tuple<string, string, string> is the perfect one.

How do I copy the content of a dictionary to an new dictionary in C#?

How can I copy a Dictionary<string, string> to another new Dictionary<string, string> so that they are not the same object?
Assuming you mean you want them to be individual objects, and not references to the same object pass the source dictionary into the destination's constructor:
Dictionary<string, string> d = new Dictionary<string, string>();
Dictionary<string, string> d2 = new Dictionary<string, string>(d);
"so that they are not the same object."
Ambiguity abound - if you do actually want them to be references to the same object:
Dictionary<string, string> d = new Dictionary<string, string>();
Dictionary<string, string> d2 = d;
(Changing either d or d2 after the above will affect both)
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
Dictionary<string, string> first = new Dictionary<string, string>()
{
{"1", "One"},
{"2", "Two"},
{"3", "Three"},
{"4", "Four"},
{"5", "Five"},
{"6", "Six"},
{"7", "Seven"},
{"8", "Eight"},
{"9", "Nine"},
{"0", "Zero"}
};
Dictionary<string, string> second = new Dictionary<string, string>();
foreach (string key in first.Keys)
{
second.Add(key, first[key]);
}
first["1"] = "newone";
Console.WriteLine(second["1"]);
}
}
A one-line version of Amal's answer:
var second = first.Keys.ToDictionary(_ => _, _ => first[_]);

Categories

Resources