Best way to display and Edit a 2D array in WPF - wpf

Seems like this would be easy to do, but it appears its not so simple. I have a 2d array of floats or ints and I'd like to display it in a grid like control so it acts similar to Excel in regards to being able to move around with the arrow keys, tab keys, etc. The size of the array will vary. This comes close, but works well only for displaying:
How to populate a WPF grid based on a 2-dimensional array

I found the easiest way would be to use datatables and create one dynamically :
DataTable dt = new DataTable();
int nbColumns = 10;
int nbRows = 5;
for (int i = 0; i < nbColumns; i++)
{
dt.Columns.Add(i.ToString(), typeof(double));
}
for (int row = 0; row < nbRows; row++)
{
DataRow dr = dt.NewRow();
for (int col = 0; col < nbColumns; col++)
{
dr[col] = col;
}
dt.Rows.Add(dr);
}
myDataGrid.ItemsSource = dt.DefaultView;
Of course this is just a random table, you can load your 2d or Xd array in your DataTable. And also, you don't have to implement IEnumerable and stuff...

Related

Ignore blank values in WPF chart control

I am working on WPF application which includes WPF chart. I am facing a situation.
I want to draw the chart only for values by ignoring blank values.
In application the data is contained by a datagrid and same data will be reflected in the graph, but datagrid having blank values(DBNull.Value).
So, I want to generate graph with only values by ignoring the blank values.
Here is my code for generating graph.
for (int col = 1; col < dtGeneric.Columns.Count; col++)
{
valueList = new List<KeyValuePair<string, double>>();
gLineSeries= new System.Windows.Controls.DataVisualization.Charting.LineSeries();
for (int row = 0; row < dtGeneric.Rows.Count - 1; row++)
{
if (string.IsNullOrEmpty(XaxisValue))
{
XaxisValue = "0";
}
YAxisValue = dtGeneric.Rows[row][col].ToString();
if (string.IsNullOrEmpty(YAxisValue))
{
YAxisValue = "0";
}
valueList.Add(new KeyValuePair<string, double>(XaxisValue, Convert.ToDouble(YAxisValue)));
}
gLineSeries.DependentValuePath = "Value";
gLineSeries.Style = gLineSeries.PolylineStyle;
gLineSeries.IndependentValuePath = "Key";
gLineSeries.ItemsSource = valueList;
gLineSeries.Title = dtGeneric.Columns[col].Caption.Replace('_', '.').ToString();
gLineSeries.AnimationSequence = AnimationSequence.FirstToLast;
chartControl.Series.Add(gLineSeries);
}
}
As you can see in the code, I have used keyvaluepair to draw the graph. So I am unable to add null value in the Value of keyvaluepair. I have tried with double.NaN but that is not working.
I have iterated all the columns because all the column will have its separate graph.
I have tried one logic to create the graph which is:
for (int col = 1; col < dtGeneric.Columns.Count; col++)
{
valueList = new List<KeyValuePair<string, double>>();
gPositionLineSeries = new System.Windows.Controls.DataVisualization.Charting.LineSeries();
for (int row = 0; row < dtGeneric.Rows.Count - 1; row++)
{
if (!string.IsNullOrEmpty(dtGeneric.Rows[row][0].ToString()) && !string.IsNullOrEmpty(dtGeneric.Rows[row][col].ToString())) //Null values will be ignored for graph generation...
{
XaxisValue = dtGeneric.Rows[row][0].ToString();
YAxisValue = dtGeneric.Rows[row][col].ToString();
valueList.Add(new KeyValuePair<string, double>(XaxisValue, Convert.ToDouble(YAxisValue)));
}
else
{
continue;
}
}
}
Above code is working fine but the X-axis values in the graph is not in order.
Please tell me some solution.
use below code in if block
string.IsNullOrEmpty(row.Cells[clm.Index].Value.ToString())

Java get field values from DefaultTableModel and format into array

I am having trouble getting two of my fields from DefaultTableModel and format them into String[].
Here is how I get data from desired fields.
model = new DataTable().Table();
int rowcount = model.getRowCount();
int[] columns = {0,1};
String[][] name = new String[columns.length][rowcount];
for (i = 0; i < columns.length; i++)
{
for (row = 0; row < rowcount; row++)
{
int column = columns[i];
name[i][row] = model.getValueAt(row, column).toString();
}
}
name[0] is firstname, name[1] is lastname. Now, would you please guide me how to combine these two fields as firstname, lastname and put it into String[] addressee?
Any inputs will be much appreciated.
I am not sure if I understand your problem. Do you need just to combine two fields?
You could create addressee directly from table.
String[] addressee = new String [rowcount];
for (row = 0; row < rowcount; row++){
addressee [row]= model.getValueAt(row, 0).toString()+" "+model.getValueAt(row, 1).toString()
}

Items and Subitems in List-View control

I'm want to use a List-View control to display results of an LDAP search in a "grid". I've written some test code to see how it works, but it's not being displayed as I want. As I understand it, each Item is equivalent to a "row" (using LVS_REPORTstyle), and the Subitem is equivalent to a "column" (e.g. for each item I can display a number of subitems, each in a separate column on the same row).
Here's my test code, currently set to create four columns, with a single Item and four Subitems (corresponding to the four columns). Two functions: one to create the columns, the other to insert items.
int CreateColumns(HWND *hwndlistbox)
{
wchar_t *cnames[100];
LVCOLUMN lvc;
int i;
cnames[0] = L"column1";
cnames[1] = L"column2";
cnames[2] = L"column3";
cnames[3] = L"column4";
cnames[4] = NULL;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
for (i = 0; cnames[i] != NULL; i++)
{
lvc.iSubItem = i;
lvc.pszText = cnames[i];
lvc.cx = 100;
lvc.fmt = LVCFMT_LEFT;
ListView_InsertColumn(*hwndlistbox, i, &lvc);
}
return i;
}
void InsertItems(HWND *hwndlistbox, int *columncount)
{
LVITEM lvi;
wchar_t *items[100];
int i, j;
items[0] = L"text1";
items[1] = L"text2";
items[2] = L"text3";
items[3] = L"text4";
items[4] = NULL;
lvi.mask = LVIF_TEXT;
lvi.iItem = 0;
for (i = 0; i < *columncount; i++)
{
lvi.pszText = items[i];
lvi.iSubItem = i;
ListView_InsertItem(*hwndlistbox, &lvi);
}
}
I expect this to generate a single row (lvi.iItem = 0;) with a text string under each column (lvi.iSubItem = i;). This is what it displays instead:
Changing lvi.iSubItem = i to lvi.iSubItem = 0 results in each text string being displayed as a new row in the first column:
I've played around with it, hardcoding the numbers on both iItem and iSubItem, changing both to i, but I can't get it to display the text anywhere other than the first column. What am I doing wrong?
First of all, your cnames and items arrays are declared as array of pointers, but you are not allocating memory for them; you would need to declare them as an array of strings, like wchar_t cnames[100][40];.
Secondly, you need to use ListView_InsertItem to insert an item and set the value for the first column, then use ListView_SetItem to add additional columns, like
lvi.pszText = items[0];
lvi.iSubItem = 0;
ListView_InsertItem(*hwndlistbox, &lvi);
for (i = 1; i < *columncount; i++)
{ lvi.pszText = items[i];
lvi.iSubItem = i;
ListView_SetItem(*hwndlistbox, &lvi);
}
Each row shows a single item so you cannot populate the columns by adding items.
As the documentation says:
"You cannot use ListView_InsertItem or LVM_INSERTITEM to insert subitems. The iSubItem member of the LVITEM structure must be zero. See LVM_SETITEM for information on setting subitems."
The LVM_SETITEM documentation explains how to set the text of a sub-item.

Two Dimension Array with Custom Type Elements

I'm trying to create on my scene an n x n size matrix, each element should be a Movie Clip, named Table, already prepared in the Library.
var tables:Array.<Table> = new Array.<Table>(tablesDimension, tablesDimension);
for (var i:int = 0; i < tablesDimension; i++) {
for (var j:int = 0; j < tablesDimension; j++) {
var tempTable:Table = new Table();
tempTable.x = i * 150 + 100;
tempTable.y = j * 100 + 100;
stage.addChild(tempTable);
tables.push(tempTable);
trace(tables[0][0].x);
}
}
A Movie Clip (in this case, Table) cannot be put in two dimensional arrays? Should I use some type conversion in my last line, at the trace(tables[0][0].x); to suggest to the compiler: it's about a Table type object?
The error message I receive: "Type parameters with non-parameterized type"
I'm not sure why you're trying to do with your first line but it's incorrect.
To quote the adobe actionscript reference:
The Array() constructor function can be used in three ways.
See this adobe reference link on Array creation. Or you can use Vectors (which are typed, like you seem to want to have).
So basically you want to create an Array, that will itself contain arrays. You need to create the arrays contained in it when you go through the first one. Else you will try to push into non existing elements. Also, you need to add the index as RST said.
var tables:Array.<Table> = new Array();
for (var i:int = 0; i < tablesDimension; i++) {
tables[i] = new Array();
for (var j:int = 0; j < tablesDimension; j++) {
var tempTable:Table = new Table();
tempTable.x = i * 150 + 100;
tempTable.y = j * 100 + 100;
stage.addChild(tempTable);
tables[i].push(tempTable);
}
}
trace(tables[0][0].x);
This should work.
I think you are missing an index. Try this
for (var i:int = 0; i < tablesDimension; i++) {
for (var j:int = 0; j < tablesDimension; j++) {
var tempTable:Table = new Table();
tempTable.x = i * 150 + 100;
tempTable.y = j * 100 + 100;
stage.addChild(tempTable);
tables[i].push(tempTable);
trace(tables[0][0].x);
}
}

Push Objects with Dynamically Allocated Names into Array - AS3

Is this possible? For example, if I had 100 items named item1.....item100, could I add them all to an array using a loop? Something along these lines....but this doesn't work obviously:
for (var i:int = 1; i <= 100; i++)
{
myArray.push("label" + 1);
}
Luckily I only have 10 items, so I can do it manually, but I'm just curious for future reference...
Thanks!
The array access operator will let you reference properties and objects by name like that, so if you have:
myArray.push(label1);
You can use this instead:
myArray.push(this["label" + 1]);
Depends on on you mean by "items".
If they are properties of the current class use:
for (var i:int = 1; i <= 100; i++)
{
myArray.push(this["label" + i]);
}
You can do this even if the names of the objects do not follow any particular pattern but they have to be inside a 'container' (you will add all objects from the container to the array):
for (var i:int = 0; i < containerName.numChildren; i++)
{
myArray.push(containerName.getChildAt(i);
}
You have to get the link to the object instance to push it into the array, for example if the names of your text fields are label1, label2, etc. you can use the following code:
for (var i:int = 1; i <= 100; i++)
{
myArray.push(labelsContainer.getChildByName("label" + i));
}

Resources