Programmatically add views to a programmatically generated view - c#

I am trying to programmatically fill a TableView such that there are 10 TableRows of 4 ImageViews. However, when I try to add ImageViews to the dynamically generated TableRows, nothing appears in the app.
I also need to store each ImageView in an array for later access, or at least store some kind of unique ID for each ImageView in said array.
My code is the following (within my MainActivity):
TableView table = FindViewById<TableLayout>(Resource.Id.tableLayout1);
for(int i = 0; i < 40; i += 4)
{
TableRow row = new TableRow(this);
row.SetGravity(GravityFlags.Center);
for (short j = 0; j < 4; j++)
{
ImageView cell = new ImageView(this);
cell.LayoutParameters = new ViewGroup.LayoutParams(75, 75);
grid[i + j] = cell
row.AddView(cell);
}
table.AddView(row);
}

There are two problems in your code, both stemming from the fact that cells in a TableRow have unique rules about their widths and heights. From the documentation:
The children of a TableRow do not need to specify the layout_width and layout_height attributes in the XML file. TableRow always enforces those values to be respectively ViewGroup+LayoutParams.MatchParent and ViewGroup+LayoutParams.WrapContent.
Even though it's talking about XML layouts, this is true for layouts created in code as well.
So, first, you need something to define the height of your ImageView cells. Generally, you'd use SetImageResource or similar to make sure the src attribute of the image view was defined (note: not the background).
Second, delete this line:
cell.LayoutParameters = new ViewGroup.LayoutParams(75, 75);
After those two changes, your code should work just fine.

Related

How to populate over multiple columns?

I am working on an 'attendance' system for the school I work at. I'm using a listview for this, but noticed that there's simply not enough space to house all employees in one list. So I want to add a second column (or at least, another 'instance' of the three columns currently used). How do I manage to get such job done?
I have been thinking about workarounds such as a second listview instance, but that would make things only more complex in my opinion. So I'd like to stick by one.
See image below for visual description of what I want to get; I want the output to first fill the left part of the listview, then the right one.
And this is the part of my code that it's (probably) about:
public void LoadEmployees()
{
lvEmployees.View = View.Details;
lvEmployees.GridLines = true;
lvEmployees.Items.Clear();
List<Employees> data = database.LoadEmployees();
for (int i = 0; i < data.Count; i++)
{
// Define the list items
ListViewItem emp = new ListViewItem(data[i].Abbreviation);
emp.SubItems.Add(data[i].Name);
emp.SubItems.Add(data[i].Status);
// Add the list items to the ListView
lvEmployees.Items.Add(emp);
}
}
With lvEmployees1 and lvEmployees2 (or left/right), two ListView.
We can simply split the List<Employees> data in half.
lvEmployees1.View = View.Details;
lvEmployees1.GridLines = true;
lvEmployees1.Items.Clear();
lvEmployees2.View = View.Details;
lvEmployees2.GridLines = true;
lvEmployees2.Items.Clear();
List<Employees> data = database.LoadEmployees();
int half = data.Count / 2;
for (int i = 0; i < data.Count; i++)
{
// Define the list items
ListViewItem emp = new ListViewItem(data[i].Abbreviation);
emp.SubItems.Add(data[i].Name);
emp.SubItems.Add(data[i].Status);
if (i <= half) lvEmployees1.Items.Add(emp);
else lvEmployees2.Items.Add(emp);
}
To create the second "grid", you can simply copy past the element in the designer.

Is it possible to pass the value of a new Cell to the Cells[x] Collection?

I need to pass the value of a new cell.
this is because I need to make the same logic as in ItextSharp, that logic being that I need to be able to create a table only by adding cells.
Instead of adding rows and then adding the cells to the rows.
var cellValue = new Cell();
((Row)Rows.LastObject).Cells[i] = cellValue;
public void Add(PdfPCell cellValue)
{
MigraRow row = null;
if (currentRowCellIndex == Columns.Count || Rows.Count == 0)
{
row = this.AddRow();
currentRowCellIndex = 0;
}
currentRowCellIndex += cellValue.Colspan;
int cellCount = ((MigraRow)Rows.LastObject).Cells.Count;
int celIndex = cellCount == 0 ? 0 : cellCount - 1;
var cell = ((MigraRow)Rows.LastObject).Cells[celIndex];
cell = cellValue.Clone();
cell.Elements = cellValue.Elements;
//((MigraRow)Rows.LastObject).Cells[celIndex]. = cellValue.Borders.Clone();
//((MigraRow)Rows.LastObject).Cells[celIndex].Borders = cellValue.Borders.Clone();
//((MigraRow)Rows.LastObject).Cells[celIndex].Elements = cellValue.Elements.Clone();
//((MigraRow)Rows.LastObject).Cells[celIndex].Shading.Color = cellValue.BackgroundColor;
//((MigraRow)Rows.LastObject).Cells[celIndex].MergeRight = cellValue.Colspan;
//para = ((Paragraph)cell.Elements.LastObject).Clone();
}
this solution doesnt work because ...Cells[i]... is read only.
but I need to do something akin to this, is it possible?
As you can see I know that I can pass the values in each property to the Cells[i], but I don't like that solution.
Ps. in the presented code the PdfPCell is just a MigraDoc cell with some added functions by me, it can be used as a regular MigraDoc cell.
Answer to the current question:
MigraDoc is not iTextSharp. You can either use MigraDoc as intended - or add a setter to overcome the "read only" limitation since MigraDoc is open source. Instead of creating a PdfPCell and changing that you could pass a reference to the cell created by MigraDoc to your code to change the contents. This should be a simple change.
Answer to the original question:
You don't have to call new Cell() - the cell will be created automatically when you call AddRow() for the table.
The code looks much nicer then without casts and such:
Row row = table.AddRow();
Cell cell = row.Cells[0];
Sample code:
http://pdfsharp.net/wiki/HelloMigraDoc-sample.ashx

Putting manually created buttons into an array

I have 100 buttons in a panel. They are named btn1-btn100. I am trying to put them into a list. This is what i have so far:
public void buttonList()
{
List<Button> panelButtonList = new List<Button>();
for (int x = 1; x <= 100; x++)
{
panelButtonList.Add(btn + x);
}
}
the name btn doesn't exist in current context? I'm new would be greatful for any assistance
List<Button> panelButtonList = this.YourPanel.Controls.OfType<Button>().ToList();
Try the above. You might have to add a where clause if there are other buttons that you don't want included. If needed you can white list based on the id range.
You need to use a FindControl method. Build your control name "btn"+Convert.ToString(x)

C# - in ListView's large icon view I cannot update icons properly

I am using ListView's large icon view, to view database inserts with image per insert.
When a new insert is made, I clear the whole ListView and add all inserts using the following code. It works perfectly, only when run for the first time.
The second time (after a new insert is added), I get all the items, but with missing images (some of them are missing and some of them are scrambled)
private void updateListView()
{
myListView.Clear();
myListView.Items.Clear();
myConnection.connect();
List<String> myValues = myConnection.getMyValues();
List<String> myImages = myConnection.getMyImages();
ImageList myImageList = new ImageList();
myImageList.ImageSize = new Size(256, 256);
myImageList.ColorDepth = ColorDepth.Depth32Bit;
for (int i = 0; i < myValues.Count; i++)
{
myListView.Items.Add(myValues[i]);
myListView.Items[i].ImageIndex = i;
myImageList.Images.Add(Image.FromFile(myImages[i]));
}
myListView.LargeImageList = myImageList;
myConnection.close();
myListView.Refresh();
}
I've checked with debug and the values/filepaths are correct.
Try associating the myListView first before you add the new item:
myListView.LargeImageList = myImageList; ,
then add item...
myImageList.Images.Add(Image.FromFile(myImages[i]));
also what is churchListView..??? where are you declaring it.. if so replace the code example to fit the churchListView or the appropriate ListView variable...
I found it:
The problem was that I had the Sort property of the ListView on.
This means that the ListView sorted it's Items automatically.
So in these lines:
myListView.Items.Add(myValues[i]);
myListView.Items[i].ImageIndex = i;
An item is added and after that the last item (i) is attached to the last image (i)
In between these lines the newly added item is auto-sorted alphabetically, so it isn't
indexed at i anymore, but something else. So the image is assigned to a random item.
Instead I did this:
ListViewItem lastAddedListViewItem = myListView.Items.Add(myValues[i]);
lastAddedListViewItem.ImageIndex = i;
And it worked

Can a table be copied to another table by an equal sign? If not, then how?

How can table controls be copied?
table2=table1?
ASP.NET C# Visual Studio 2008 table control.
The reason is that it works for strings. Assume the below strings to be tables.
string full;
string userinput;
full = full + userinput;
Edit: Since answering this question back in June 2010, I have spent a lot of time using jQuery to do this kind of thing on the client. If interested in this approach, look into the jQuery clone() and append(), after(), before() and related methods.
End Edit
No, you can't. Table, like any other control, is a reference type. It means that copying it just copies a reference to the real object instance. Because it doesn't implement System.ICloneable you have to create a new one and then copy properties manually one by one.
I would be curious to know why you are trying to do this, because it doesn't seem to follow any of the best practices that I am familiar with. Could you describe what you are trying to do?
One thing you could do is copy the contents of a table, although this won't copy the other properties such as styles and cell-padding etc:
protected void CopyTable()
{
var clontable= new HtmlTable();
var mytbl = form1.FindControl("mytable") as HtmlTable;
if (mytbl != null)
{
HtmlTableRow myrow;
HtmlTableCell mycell;
for (int i = 0; i < mytbl.Rows.Count - 1; i++)
{
myrow = new HtmlTableRow();
for (int j = 0; j < mytbl.Rows[i].Cells.Count - 1; j++)
{
mycell = new HtmlTableCell();
mycell.InnerHtml = mytbl.Rows[i].Cells[j].InnerHtml;
myrow.Cells.Add(mycell);
}
clontable.Rows.Add(myrow);
}
form1.Controls.Add(clontable);
}
}

Categories