WPF Bind Dictionary to combobox - c#

I have the List of double Arrays. Some values are predefined. And I want to bind this list to DataGrid. Actually datagrid cells are comboboxes filled with Dictionary Values. The idea is that user selects any value from dropdown and appropriate Key is written to List with double Arrays. Code is the following:
Dictionary<int, string> scores = new Dictionary<int, string>();
scores.Add(1, "the same");
scores.Add(3, "moderate superiority");
scores.Add(5, "strong superiority");
scores.Add(7, "very strong superiority");
scores.Add(9, "extremely superiority");
//define number of alternatives
int num = Alternatives.Children.Count - 1;
//initialize matrix for assessment scores
List<double[]> gridAssessment = new List<double[]>();
for (int i = 0; i < num; i++)
{
gridAssessment.Add(new double[num]);
}
//set initial values
for (int i = 0; i < num; i++)
{
gridAssessment[i][i] = scores.ElementAt(0).Key;
}
//define source for assessment grid
grAssessment.ItemsSource = gridAssessment;
grAssessment.AutoGenerateColumns = false;
//add columns to the grid
for (int i = 0; i < num; i++)
{
DataGridComboBoxColumn col = new DataGridComboBoxColumn();
grAssessment.Columns.Add(col);
col.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
//define source for comboboxes
col.ItemsSource = scores;
col.DisplayMemberPath = "Value";
col.SelectedValuePath = "Key";
string a = "[" + i.ToString() + "]";
Binding t = new Binding(a);
t.Mode = BindingMode.TwoWay;
col.SelectedValueBinding = t;
Actually when I select any value from dropdown validation mark appears. Could you please assist me with this binding?
Thanks a lot.

The issue resides here:
//initialize matrix for assessment scores
List<double[]> gridAssessment = new List<double[]>();
for (int i = 0; i < num; i++)
{
gridAssessment.Add(new double[num]);
}
Checking the Output window, it says it "cannot convert back". So when it tries to convert a double back to an int, it has a problem. If you change this to int to match the "scores" data type, the validation will be gone.
Fixed Code:
//initialize matrix for assessment scores
List<int[]> gridAssessment = new List<int[]>();
for (int i = 0; i < num; i++)
{
gridAssessment.Add(new int[num]);
}

Related

C# - All objects are getting the same values

I am coding a chart. This is my code:
for (int i = 0; i < 2; i++)
{
Val= new ChartValues<ObservablePoint>(); // added
Val.Clear(); // added
lineSeries = new LineSeries
{
Title = "Graph " + i,
Values = Val,
Stroke = Brushes.Blue,
Fill = Brushes.Transparent,
LineSmoothness = 0,
PointGeometry = null
};
for (int jj = 0; jj < 2; jj++)
{
Val.Add(new ObservablePoint
{
X = jj+i+1,
Y = jj+i+1
});
}
Col.Add(lineSeries);
}
The problem is that in my Col variable (collection) all series are getting the latest values of the loop, which results are lineSeries are the same.
When I use the lineSeries = new LineSeries{}, it should create a new independent object right? Or do I have to erase and create it?
Any help is appreciated.
The issue is that you're reusing the same variable Val to store the actual values. Where is it declared, is it a list? Create a new one each time inside the outer loop and then use it to construct the LineSeries.
for (int i = 0; i < 2; i++)
{
var Val = new ChartValues<ObservablePoint>();
for (int jj = 0; jj < 2; jj++)
{
Val.Add(new ObservablePoint
{
X = jj+i+1,
Y = jj+i+1
});
}
var lineSeries = new LineSeries
{
Title = "Graph " + i,
Values = Val,
Stroke = Brushes.Blue,
Fill = Brushes.Transparent,
LineSmoothness = 0,
PointGeometry = null
};
Col.Add(lineSeries);
}
the problem is in line series, you use the same variable, and you are adding the same variable. It it changing each time, and in the end have the last data
lineSeries = new LineSeries
{
......
};
should be
var lineSeries = new LineSeries
{
......
};

Generate a grid of (ListView)'s in Visual Studio c#

I'm trying to create a panel(Static) in C#, were I generate multiple ListViews/GridViews in a Grid.
I know how to Fill a single existing ListView.
I've done this multiple times on ListViews I dragged onto my application using the toolbox.
I have a sqldatabase connection and I want to use data from that database to determine how many ListViews/GridViews are going to be generated.
I found a picture of what I am imagining in my head(Without the roomstatus)
If there are more ListViews/GridViews generated I want to be able to scroll down INSIDE the panel i created.
Okay, i've managed to pull it of!
private void GenerateTable()
{
SomerenLogic.Room_Service roomService = new SomerenLogic.Room_Service();
List<Room> roomList = roomService.GetRooms();
int counter = 0;
foreach (SomerenModel.Room s in roomList)
{
counter = counter + 1;
}
double wortelvan = Math.Sqrt(counter);
double column = Math.Floor(wortelvan);
double row = Math.Ceiling(wortelvan);
int columnCount = (int)(column);
int rowCount = (int)(row);
SomerenLogic.Indeling_Service indelingService = new SomerenLogic.Indeling_Service();
//Clear out the existing controls, we are generating a new table layout
tableLayoutPanel1.Controls.Clear();
tableLayoutPanel1.RowStyles.Clear();
//Clear out the existing row and column styles
tableLayoutPanel1.ColumnStyles.Clear();
tableLayoutPanel1.RowStyles.Clear();
//Now we will generate the table, setting up the row and column counts first
tableLayoutPanel1.ColumnCount = columnCount;
tableLayoutPanel1.RowCount = rowCount;
int counter2 = 1;
for (int x = 0; x < columnCount; x++)
{
//First add a column
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent));
for (int y = 0; y < rowCount; y++)
{
//Next, add a row. Only do this when once, when creating the first column
if (x == 0)
{
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent));
}
////Create the control, in this case we will add a button
//Button cmd = new Button();
//cmd.Text = string.Format("({0}, {1})", x, y);
////Finally, add the control to the correct location in the table
ListView listView1 = new ListView();
listView1.Columns.Add("");
listView1.View = View.Details;
listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
listView1.Scrollable = false;
listView1.GridLines = true;
listView1.AutoArrange = true;
List<Indeling> indelingList = indelingService.GetIndeling(counter2);
foreach (SomerenModel.Indeling s in indelingList)
{
ListViewItem la = new ListViewItem("Kamer nummer: "+(s.KamerNummer).ToString());
listView1.Items.Add(la);
ListViewItem lb = new ListViewItem("Type kamer: "+(s.TypeKamer).ToString());
listView1.Items.Add(lb);
ListViewItem lc = new ListViewItem("Plekken: "+(s.AantalBedden).ToString());
listView1.Items.Add(lc);
listView1.Height = (listView1.Items.Count * 19);
tableLayoutPanel1.Controls.Add(listView1, x, y);
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}
counter2++;
}
}
}

How do I use For Loop twice to find datatable columns and rows?

I want to use for loop to get average of datatable columns and rows. What I want to do is that what if there are 100 ~ 1000 columns and rows, I can't keep on adding them in the code. is there one simple code that can get average of automatically as I add columns and rows?
here is my code, I am stuck I don't know what to write in ?? area below and this code gets me error please help...
private void button1_Click(object sender, EventArgs e)
{
DataTable dtGrid = gridData.DataSource as DataTable;
DataTable dtResult = new DataTable();
Math columnIndex = new Math();
List<double> avgList = new List<double>();
for (int i = 0; i < dtGrid.Columns.Count; i++)
{
for (int k = 1; k < dtGrid.Rows.Count; k++)
{
// ??
avgList.Add(Convert.ToDouble(dtGrid.Rows[i].ToString()));
}
}
//this is from other class name Math
/* public double getAverageValue(List<double> avgList)
{
double averageList = 0;
averageList = MathNet.Numerics.Statistics.Statistics.Mean(avgList.ToList());
return averageList;
}*/
double averageX1 = columnIndex.getAverageValue(avgList);
List<Math> list = new List<Math>();
//using get; set from other class
list.Add(new Math { Result = "Average", X1 = averageX1.ToString() });
gridData2.DataSource = list;
}
}
}
It looks like your loop is inside out. Try this:
DataTable dtGrid = gridData.DataSource as DataTable;
DataTable dtResult = new DataTable();
Math columnIndex = new Math();
List<double> avgList = new List<double>();
for (int k = 1; k < dtGrid.Rows.Count; k++)
{
for (int i = 0; i < dtGrid.Columns.Count; i++)
{
// ??
avgList.Add(Convert.ToDouble(dtGrid.Rows[k].Columns[i].ToString()));
}
}
This logic averages all columns in a row together. If you need,, you can create a Dictionary and average each column separately. Something like thisL
Dictionary<int, List<double>> AvgColumnList = new Dictionary<int, System.Collections.Generic.List<double>>();
This uses a dictionary that contains a list for each column in the row. If there are 100 columns, then there will be 100 entries in the dictionary with index 0 - 99. Each dictionary item will contain a list of doubles.
for (int k = 1; k < dtGrid.Rows.Count; k++)
{
for (int i = 0; i < dtGrid.Columns.Count; i++)
{
if (!AvgColumnList.Keys.Contains(i))
AvgColumnList.Add(i, new List<double>());
AvgColumnList[i].Add(Convert.ToDouble(dtGrid.Rows[k].Columns[i].ToString()));
}
}
DataTable is zero index based, in your code row count started from 1 it should be 0, also dtGrid.Rows[i] is a row not the cell value. Use below code to loop through each cell of a DataTable
Update : Code updated as OP want to save each column data separately and irrespective of column numbers.
List<List<double>> perColumnAvg = new List<List<double>>();
for (int i = 0; i < dtGrid.Columns.Count; i++)
{
avgList = new List<double>();
for (int k = 0; k < dtGrid.Rows.Count; k++)
{
// ??
avgList.Add(Convert.ToDouble(dtGrid.Rows[k][i].ToString()));
}
perColumnAvg.Add(avgList);
}
Now you can compute individual column average as
foreach (var columnList in perColumnAvg)
{
// place your logic here.
columnIndex.getAverageValue(columnList);
}
And can compute avg across table using.
double tableAvg = columnIndex.getAverageValue(perColumnAvg.SelectMany(s=>s));

How do you retrieve inputted text from a textbox array?

I am creating a calculator where the user enters a number into a textbox specifing how many inputs (textboxes) the user wants to have (Code not shown). I have used a textbox array to create these textboxes. The problem comes when I want to get the text from these textboxes to perform the calculations, the code I have written so far for this is shown below:
int n;
TextBox[] textBoxes;
Label[] labels;
double[] values;
public void GetValue()
{
n = Convert.ToInt16(txtInputFields.Text);
values = new double[n];
textBoxes = new TextBox[n];
for (int i = 0; i < n; i++)
{
}
}
I am unsure what to put in the for loop for this; I have tried the following:
values[n] = Convert.toDouble(textBoxes[n].Text);
but it gives me the error: Index was outside the bounds of the array.
I am new to C# and programming in general so any help would be much appreciated.
Thanks.
EDIT: Code to create textboxes is shown here:
public void InstantiateTextFields()
{
n = Convert.ToInt16(txtInputFields.Text);
int posLeft = 100;
textBoxes = new TextBox[n];
labels = new Label[n];
// Creates number of inputs and labels as specified in txtInputFields (n).
for (int i = 0; i < n; i++)
{
textBoxes[i] = new TextBox();
textBoxes[i].Top = 100 + (i * 30);
textBoxes[i].Left = posLeft;
textBoxes[i].Name = "txtInput" + (i + 1);
labels[i] = new Label();
labels[i].Top = 100 + (i * 30);
labels[i].Left = posLeft - 50;
labels[i].Text = "Input " + (i + 1);
labels[i].Name = "lblInput" + (i + 1);
}
for (int i = 0; i < n; i++)
{
this.Controls.Add(textBoxes[i]);
this.Controls.Add(labels[i]);
}
}
Your code in the GetValue method recreates the array of textboxes and doing so destroys the orginal content (the textboxes dynamically created InstantiateTextFields).
In this way your loop fails with Object Reference not set.
You just need to use the global variable without reinitiaizing it
public void GetValue()
{
n = Convert.ToInt16(txtInputFields.Text);
values = new double[n];
// textBoxes = new TextBox[n];
for (int i = 0; i < n; i++)
{
values[i] = Convert.ToDouble(textBoxes[i].Text);
}
}
There is something to be said about reading the input text and converting it to double without checks. If your user types something that cannot be converted to a double your code will crash on the Convert.ToDouble line. Use instead
double temp;
for (int i = 0; i < n; i++)
{
if(double.TryParse(textBoxes[i].Text, out temp)
values[i] = temp;
else
{
// Not a double value....
// A message to your user ?
// fill the array with 0 ?
// Your choice....
}
}
values[n] = Convert.toDouble(textBoxes[n].Text); gives you error because n is outside of the array. You allocate an array with the size of n which is zero indexed aka the last element is at position n-1.
for (int i = 0; i < n; i++)
{
values[i] = Convert.toDouble(textBoxes[i].Text);
}

Binding a WPF DataGrid to a List<List<int>> object

I try to bind a DataGrid in WPF to a list of lists.
I am doing this:
private List<List<int>> _rows = new List<List<int>>();
private void WindowLoaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 2; i++)
{
var row = new List<int>();
for (int j = 0; j < 2; j++)
{
row.Add(j);
}
_rows.Add(row);
}
var dg1 = new DataGrid();
for (int i = 0; i < 2; i++)
{
var col = new DataGridTextColumn();
col.Header = i.ToString();
dg1.Columns.Add(col);
}
dg1.ItemsSource = _rows;
this.LayoutRoot.Children.Add(dg1);
}
When I run the program the DataGrid remains empty nothing works.
how should I do to get this work?
You can't just bind a list of value types to a WPF DataGrid.
You need to create a wrapper class for the int and specify the binding, as specified in this answer.
You never acually add an int to any List. You added a List<Int> but never an Int.
You iterate rows (not columns) (_row.count will give you a row count) to add dg1 comlumns.
It needs more help that just this but this is a start
for (int j = 0; j < 2; j++)
{
var row = new List<int>();
for (int i = 0; i < 2; i++)
{
row.add(i);
}
_rows.Add(row);
}

Categories

Resources