I have a datagridview with a bound combobox column which contains decimal value. There is a range of valid decimal values so user can choose one of them. However I face a strange problem - when you click on a combobox in the selected value somehow resets to the first one in a list thus losing the one already selected. Look at the pictures
This is the initial view of a window:
This is when I select similar column with a double value in it(note the selection in combobox's list)
This is when I select column with a decimal value. The selection(number 293) is missing
Here is the code I use:
public Form1()
{
InitializeComponent();
dgwResult.AutoGenerateColumns = false;
var list = new List<string>(){"A", "B", "C", "D"};
var list2 = new List<double>();
var list3 = new List<decimal>();
for (int i = 0; i < 300; i++)
{
list2.Add((double)i);
list3.Add((decimal)i);
}
dgw_2.DataSource = list;
dgw_2.DataPropertyName = "two";
dgw_3.DataSource = list2;
dgw_3.DataPropertyName = "three";
dgw_4.DataSource = list3;
dgw_4.DataPropertyName = "four";
DataTable dt = new DataTable();
dt.Columns.Add("one", typeof(string));
dt.Columns.Add("two", typeof(string));
dt.Columns.Add("three", typeof(double));
dt.Columns.Add("four", typeof(decimal));
dt.Rows.Add(new object[] { "akjsgdf", "A", 10.0, 10.0m });
dt.Rows.Add(new object[] { "akjsgdf", "B", 15.0, 15.0m });
dt.Rows.Add(new object[] { "akjsgdf", "C", 20.0, 20.0m });
dt.Rows.Add(new object[] { "akjsgdf", "D", 15.0, 15.0m });
dt.Rows.Add(new object[] { "akjsgdf", "C", 293.0, 293.0m });
dgwResult.DataSource = dt;
}
private void InitializeComponent()
{
this.dgwResult = new System.Windows.Forms.DataGridView();
this.dgw_1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dgw_2 = new System.Windows.Forms.DataGridViewComboBoxColumn();
this.dgw_3 = new System.Windows.Forms.DataGridViewComboBoxColumn();
this.dgw_4 = new System.Windows.Forms.DataGridViewComboBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.dgwResult)).BeginInit();
this.SuspendLayout();
//
// dgwResult
//
this.dgwResult.AllowUserToAddRows = false;
this.dgwResult.AllowUserToDeleteRows = false;
this.dgwResult.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dgwResult.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dgwResult.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dgw_1,
this.dgw_2,
this.dgw_3,
this.dgw_4});
this.dgwResult.Location = new System.Drawing.Point(12, 12);
this.dgwResult.Name = "dgwResult";
this.dgwResult.RowHeadersVisible = false;
this.dgwResult.Size = new System.Drawing.Size(268, 150);
this.dgwResult.TabIndex = 0;
this.dgwResult.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgwResult_CellClick);
//
// dgw_1
//
this.dgw_1.DataPropertyName = "one";
this.dgw_1.HeaderText = "One";
this.dgw_1.Name = "dgw_1";
//
// dgw_2
//
this.dgw_2.DataPropertyName = "two";
this.dgw_2.HeaderText = "Two";
this.dgw_2.Name = "dgw_2";
//
// dgw_3
//
this.dgw_3.DataPropertyName = "three";
this.dgw_3.HeaderText = "Double";
this.dgw_3.Name = "dgw_3";
//
// dgw_4
//
this.dgw_4.DataPropertyName = "four";
this.dgw_4.HeaderText = "Decimal";
this.dgw_4.Name = "dgw_4";
this.dgw_4.Resizable = System.Windows.Forms.DataGridViewTriState.True;
this.dgw_4.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.dgwResult);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.dgwResult)).EndInit();
this.ResumeLayout(false);
}
private System.Windows.Forms.DataGridView dgwResult;
private System.Windows.Forms.DataGridViewTextBoxColumn dgw_1;
private System.Windows.Forms.DataGridViewComboBoxColumn dgw_2;
private System.Windows.Forms.DataGridViewComboBoxColumn dgw_3;
private System.Windows.Forms.DataGridViewComboBoxColumn dgw_4;
Can someone point out why the behavior is so strange for decimal? Maybe I'm missing something simple here?
The reason you're getting that 'strange' operation is because the decimal numbers are not in the list used to populate the column's DataSource.
The problem is fixed by changing the code that populates the DataTable to this:
dt.Rows.Add(new object[] { "akjsgdf", "A", 10.0, 10m });
dt.Rows.Add(new object[] { "akjsgdf", "B", 15.0, 15m });
dt.Rows.Add(new object[] { "akjsgdf", "C", 20.0, 20m });
dt.Rows.Add(new object[] { "akjsgdf", "D", 15.0, 15m });
dt.Rows.Add(new object[] { "akjsgdf", "C", 293.0, 293m });
I reckon the DataGridView calls the .ToString() function on each element in the column's DataSource to find the match. Since 1.0 does not equal 1 (in string terms), no item is selected when you open the drop down menu of the combo box.
Related
I have a DataGridView that is being filled with DataTable → Fill() method.
I want to add another Table in the same DataGridView, in the next column, just when the other one ends. Is it possible?
Now I have something like this
da.Fill(dt);
dataGridView1.DataSource = null;
dataGridView1.Rows.Clear();
dataGridView1.DataSource = dt;
I want to add another DataTable to the same DataGridView in new columns. Thanks
Use the Merge function of DataTable and then shift elements up. See codes below:
private void AddTwoDataTable()
{
DataTable dt1 = new DataTable();
dt1.Columns.Add("ID1", typeof(int));
dt1.Columns.Add("Value1", typeof(string));
dt1.Columns.Add("Value2", typeof(string));
DataTable dt2 = new DataTable();
dt2.Columns.Add("ID2", typeof(int));
dt2.Columns.Add("Value3", typeof(string));
dt1.Rows.Add(new object[] { 1, "a", "ab"});
dt1.Rows.Add(new object[] { 2, "b", "bc" });
dt1.Rows.Add(new object[] { 3, "c", "cd" });
dt1.Rows.Add(new object[] { 4, "d", "de" });
dt2.Rows.Add(new object[] { 101, "x" });
dt2.Rows.Add(new object[] { 102, "y" });
dt2.Rows.Add(new object[] { 103, "y" });
var newtable = MergetwoTables( dt1, dt2 );
dataGridView1.DataSource = newtable;
}
public static DataTable MergetwoTables(DataTable dt1, DataTable dt2)
{
DataTable table = new DataTable("NewTable");
table.Merge(dt1);
table.Merge(dt2);
int maxRows1 = dt1.Rows.Count;
int maxColu1 = dt1.Columns.Count;
int maxRows2 = dt2.Rows.Count;
int maxColu2 = dt2.Columns.Count;
// copy elements from new rows
for (int r = maxRows1; r < maxRows1 + maxRows2; r++)
for (int c = maxColu1; c < maxColu1 + maxColu2; c++)
table.Rows[r - maxRows1][c] = table.Rows[r][c];
//delete new rows
var maxrows = maxRows1 > maxRows2 ? maxRows1 : maxRows2;
for (int r = maxRows1 + maxRows2 - 1; r >= maxrows; r--)
table.Rows[r].Delete();
return table;
}
Output:
How do I create a method setOutput() that calculates and sets the max output of each item (a,b,c,d) in Formula by multiplying the percentage in Formula to the amt in Item through its common id? I think I worked out the logic but I don't know how to use the id to reference values for calculation.
I.e. how do I reference values by their id within arrays in a nested foreach loop?
Class Item {
public string id { get;set }
public double? amt { get;set } }
Class Formula {
public string id { get;set }
public double? percent { get;set }
public double? output { get;set } }
Item[] inventory = {
new Item { id = "a", amt = 111.1},
new Item { id = "b", amt = 222.2},
new Item { id = "c", amt = 333.3,
new Item { id = "d", amt = 400.4} }
Formula[] formulas = { new Formula {
{id = "a", percent=25.0, output = null},
{id = "b", percent=25.0, output = null},
{id = "c", percent=25.0, output = null},
{id = "d", percent=25.0, output = null}; },
new Formula {
{id = "a", percent=20.0, output = null};
{id = "b", percent=20.0, output = null};
{id = "c", percent=60.0, output = null};
{id = "d", percent= 0.0, output = null}; },
new Formula {
{id = "a", percent=30.0, output = null};
{id = "b", percent=30.0, output = null};
{id = "c", percent=20.0, output = null};
{id = "d", percent=20.0} output = null}; } }
setOutput(Item[] inventory, Formula[] formulas)
{
// Loop through each Formula in formulas
// Loop through each Item in
// Item.amt * Formula.percentage/100 = Formula.amt
foreach (var Formula in formulas) //
{
foreach (Item item in Raw)
{
(id="a") Raw.amt* Formula.percent/100 = Formula.output
(id="b") Raw.amt* Formula.percent/100 = Formula.output
(id="c") Raw.amt* Formula.percent/100 = Formula.output
(id="d") Raw.amt* Formula.percent/100 = Formula.output
}
}
}
Hi assuming if your Item array has Items with unique id's something like below in your code
Item[] inventory = {new Item { id = "a", amt = 111.1},
new Item { id = "b", amt = 222.2},
new Item { id = "c", amt = 333.3 },
new Item { id = "d", amt = 400.4} };
Formula[] formulas = { new Formula {id = "a", percent=25.0, output = null} ,
new Formula {id = "b", percent=25.0, output = null} ,
new Formula {id = "c", percent=25.0, output = null},
new Formula {id = "d", percent=25.0, output = null} };
Then in your setouput function you could do something like below to set your output property in formulas array
formulas.ToList().ForEach(var => var.output = var.percent * inventory.First(var1 => var1.id == var.id).amt / 100);
A better approach is to make formulas data type from Formula[] to List
Assuming you meant for your formulas to be List<Formula>[] so you could have lists of Formulas, converting the inventory of Items to a Dictionary makes it easy:
void setOutput(Item[] inventory, List<Formula>[] formulas) {
var Raw = inventory.ToDictionary(i => i.id, i => i.amt);
foreach (var FormulaSet in formulas)
foreach (var formula in FormulaSet)
formula.output = Raw[formula.id] * formula.percent / 100;
}
I have data table having rows like
ID Name
2 A
4 B
3 C
5 D
1 E
List order = new List() { "1", "3", "2", "5", "4" }
--------------order by list-----------------
ID Name
1 E
3 C
2 A
5 D
4 B
can anyone help to implement this.. I am using DataTable in Winforms.
Another solution to the already given ones, would be to loop your order list and then sort your source list.
// source list
List<Foo> lSource = new List<Foo>() {
new Foo() { ID = 2, Name = "A" },
new Foo() { ID = 4, Name = "B" },
new Foo() { ID = 3, Name = "C" },
new Foo() { ID = 5, Name = "D" },
new Foo() { ID = 1, Name = "E" },
};
// order list
List<int> order = new List<int>() { 1, 3, 2, 5, 4 };
// loop order list and sort source list
order.ForEach(x =>
{
lSource = lSource.OrderBy(g => g.ID == x).ToList();
});
// set datasource
dataGridView1.DataSource = lSource;
I just added a class Foo containing an int ID and a string Name, because you didn't share your whole code.
I think you can join your order and your datatable with AsEnumerable method and on on part you can equalize both of them and select rows, then you can generate a DataTable from that query with CopyToDataTable method.
var dt = new DataTable();
var dc = new DataColumn() { ColumnName = "ID", DataType = typeof(string) };
dt.Columns.Add(dc);
dc = new DataColumn() { ColumnName = "Name", DataType = typeof(string) };
dt.Columns.Add(dc);
dt.Rows.Add(new object[] { "2", "A" });
dt.Rows.Add(new object[] { "4", "B" });
dt.Rows.Add(new object[] { "3", "C" });
dt.Rows.Add(new object[] { "5", "D" });
dt.Rows.Add(new object[] { "1", "E" });
List<string> order = new List<string>() { "1", "3", "2", "5", "4" };
var query = from item in order
join row in dt.AsEnumerable() on item equals row.Field<string>("ID")
select row;
var result = query.CopyToDataTable();
result will be;
I'm not sure this is the best way or not but this seems to fit with your case.
You can join both lists (the one with items and the one with sorted id's) and then select the items:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var list = new List<Item>{
new Item { Id = 2, Text = "A" },
new Item { Id = 4, Text = "B" },
new Item { Id = 3, Text = "C" },
new Item { Id = 5, Text = "D" },
new Item { Id = 1, Text = "E" }
};
var sortorder = new List<int> { 1, 3, 2, 5, 4 };
var sortedlist = sortorder.Join(list, x => x, y => y.Id, (x,y) => y);
foreach(var item in sortedlist)
Console.WriteLine("{0} {1}", item.Id, item.Text);
}
}
I am trying to re-write a method using TDD.
Here is the original method without the database logic and below it is my attempt to re-write it. Its not complete as I just hit a wall and do not understand how to finish it.
I'm trying to learn and can't work it out so need some help. Thanks for reading.
//Original Method
public class StringCalculator()
{
public List<ShipmentInformation> GetBoxRange(int BoxSize, int Quantity, ref string DVDType, ref string ErrorMessage)
{
//Get Connection String
//Do Database Queries and return shipmentInfo variable as List<ShipmentInformation>
var DVDTotals = shipmentInfo.GroupBy(x => x.DVDType).Select(x => new { DVDType = x.Key, Total = x.Sum(y => (y.DVDEndID - y.DVDStartID) + 1) });
if (DVDTotals.Count() == 0 || DVDTotals.All(x => x.Total < Quantity))
{
ErrorMessage = "There is not enough data to create a shipment based on the quantity";
return new List<ShipmentInformation>();
}
//Select the one with the largest amount of stock
var LargestDVDType = DVDTotals.Aggregate((l, r) => l.Total > r.Total ? l : r).DVDType;
var LargestDVDTypeSelection = shipmentInfo.Where(x => x.DVDType == LargestDVDType);
long previousDVDStartID = 0;
//Make sure ranges are sequential
List<ShipmentInformation> SequentialBoxResults = new List<ShipmentInformation>();
foreach (var item in LargestDVDTypeSelection)
{
if (item.DVDStartID - previousDVDStartID == BoxSize || previousDVDStartID == 0)
{
SequentialBoxResults.Add(item);
}
else
{
SequentialBoxResults.Clear();
SequentialBoxResults.Add(item);
}
previousDVDStartID = item.DVDStartID;
if (BoxSize * SequentialBoxResults.Count == Quantity)
{
break;
}
}
if (SequentialBoxResults.Count == 0 || BoxSize * SequentialBoxResults.Count != Quantity)
{
ErrorMessage = "There are no available ranges to create a shipment based on the quantity";
return new List<ShipmentInformation>(); ;
}
List<ShipmentInformation> Results = new List<ShipmentInformation>();
var Genres = SequentialBoxResults.GroupBy(x => x.Genre);
foreach (var Genre in Genres)
{
var orderedGenres = Genre.OrderBy(x => x.DVDStartID);
ShipmentInformation shipment = new ShipmentInformation();
shipment.Genre = Genre.Key;
shipment.DVDStartID = orderedGenres.First().DVDStartID;
var lastItem = orderedGenres.Last();
shipment.DVDEndID = lastItem.DVDEndID;
shipment.DVDType = lastItem.DVDType;
Results.Add(shipment);
}
//We have our shipment recordsnow split them up if any are over 75000
for (int i = 0; i < Results.Count; i++)
{
long rangeSize = Results[i].DVDEndID - Results[i].DVDStartID + 1;
double noOfLoops = Math.Ceiling(rangeSize / 75000D);
long remainder = rangeSize % 75000;
if (noOfLoops > 1)
{
bool AddedRecord = false;
for (int j = 0; j < noOfLoops; j++)
{
long shipmentSize = 0;
if (j == (noOfLoops - 1))
{
shipmentSize = remainder;
if (AddedRecord)
Results.Add(new ShipmentInformation() { DVDStartID = Results.Last().DVDEndID + 1, DVDEndID = Results.Last().DVDEndID + 1 + (shipmentSize - 1), Genre = Results.Last().Genre });
else
Results.Add(new ShipmentInformation() { DVDStartID = Results[i].DVDEndID + 1, DVDEndID = Results[i].DVDEndID + 1 + (shipmentSize - 1), Genre = Results[i].Genre });
}
else
{
shipmentSize = 75000;
if (j == 0)
{
Results[i].DVDEndID = Results[i].DVDStartID + (shipmentSize - 1);
}
else if (j == 1)
{
Results.Add(new ShipmentInformation() { DVDStartID = Results[i].DVDEndID + 1, DVDEndID = Results[i].DVDEndID + 1 + (shipmentSize - 1), Genre = Results[i].Genre });
AddedRecord = true;
}
else
{
Results.Add(new ShipmentInformation() { DVDStartID = Results.Last().DVDEndID + 1, DVDEndID = Results.Last().DVDEndID + 1 + (shipmentSize - 1), Genre = Results.Last().Genre });
AddedRecord = true;
}
}
}
}
}
return Results;
}
}
//New Method with Tests
public List<ShipmentInformation> GetBoxRange(int BoxSize, int Quantity, DateTime CutOffDate, IDataProvider Provider, ref string DVDType, ref string ErrorMessage)
{
if (BoxSize == 0)
{
ErrorMessage = "Please enter a BoxSize";
}
if (Quantity == 0)
{
ErrorMessage = "Please enter a Quantity";
}
if (!String.IsNullOrWhiteSpace(ErrorMessage))
{
return new List<ShipmentInformation>();
}
List<ShipmentInformation> Data = Provider.GetData();
if (Data.Count == 0)
{
ErrorMessage = "Database failed to return data";
return new List<ShipmentInformation>();
}
List<ShipmentInformation> OrderedData = GetSequentialBoxes(Data, BoxSize, Quantity);
if (OrderedData.Count == 0)
{
ErrorMessage = "No sequential data found";
return new List<ShipmentInformation>();
}
//I'm not sure how to continue from here - I started writing GetRecordsPerGenre but got lost in what I'm trying to do. I still need to check if size is over 75000
return OrderedData;
}
public virtual List<ShipmentInformation> GetSequentialBoxes(List<ShipmentInformation> Data, int BoxSize, int Quantity)
{
if (Data.Count == 0)
return new List<ShipmentInformation>();
var orderedData = Data.OrderBy(x => x.DVDStartID);
if (!orderedData.SequenceEqual(Data))
return new List<ShipmentInformation>();
var DVDTotals = Data.GroupBy(x => x.DVDType).Select(x => new { DVDType = x.Key, Total = x.Sum(y => (y.DVDEndID - y.DVDStartID) + 1) });
if (DVDTotals.Count() == 0 || DVDTotals.All(x => x.Total < Quantity))
{
return new List<ShipmentInformation>();
}
var LargestDVDType = DVDTotals.Aggregate((l, r) => l.Total > r.Total ? l : r).DVDType;
Data = Data.Where(x => x.DVDType == LargestDVDType).ToList();
List<ShipmentInformation> returnData = new List<ShipmentInformation>();
long previousDVDStartID = 0;
foreach (var item in Data)
{
if (previousDVDStartID == 0 || item.DVDStartID - previousDVDStartID == BoxSize)
{
returnData.Add(item);
}
else
{
returnData.Clear();
returnData.Add(item);
}
previousDVDStartID = item.DVDStartID;
if (returnData.Count * BoxSize == Quantity)
break;
}
return returnData.OrderBy(x => x.DVDStartID).ToList();
}
public List<ShipmentInformation> GetRecordsPerGenre(List<ShipmentInformation> Data)
{
List<ShipmentInformation> Results = new List<ShipmentInformation>();
var Genres = Data.GroupBy(x => x.Genre);
foreach (var Genre in Genres)
{
var orderedGenres = Genre.OrderBy(x => x.DVDStartID);
ShipmentInformation shipment = new ShipmentInformation();
shipment.Genre = Genre.Key;
shipment.DVDStartID = orderedGenres.First().DVDStartID;
var lastItem = orderedGenres.Last();
shipment.DVDEndID = lastItem.DVDEndID;
shipment.DVDType = lastItem.DVDType;
Results.Add(shipment);
}
return Results;
}
//Tests
[TestFixture]
public class GetBoxRangeMethod
{
private StringCalculator CreateNewCalculator()
{
return new StringCalculator();
}
[TestCase(0, 1)]
[TestCase(1, 0)]
public void ZeroValuesForBoxSizeOrQuantity_ReturnsErrorAndEmptyList(int BoxSize, int Quantity)
{
StringCalculator sc = CreateNewCalculator();
string ErrorMessage = "";
string ChipType = "";
FakeDataProvier provider = new FakeDataProvier(new List<ShipmentInformation>());
List<ShipmentInformation> result = sc.GetBoxRange(BoxSize, Quantity, new DateTime(2012, 01, 01), "A", provider, ref ChipType, ref ErrorMessage);
Assert.AreNotEqual("", ErrorMessage);
Assert.AreEqual(0, result.Count);
}
[Test]
public void EmptyBookTypeString_ReturnsErrorAndEmptyList()
{
StringCalculator sc = CreateNewCalculator();
string ErrorMessage = "";
string ChipType = "";
FakeDataProvier provider = new FakeDataProvier(new List<ShipmentInformation>());
List<ShipmentInformation> result = sc.GetBoxRange(1, 1, new DateTime(2012, 01, 01), "", provider, ref ChipType, ref ErrorMessage);
Assert.AreNotEqual("", ErrorMessage);
Assert.AreEqual(0, result.Count);
}
[Test]
public void EmptyDBData_ReturnsErrorAndEmptyList()
{
StringCalculator sc = CreateNewCalculator();
string ErrorMessage = "";
string ChipType = "";
FakeDataProvier provider = new FakeDataProvier(new List<ShipmentInformation>());
List<ShipmentInformation> result = sc.GetBoxRange(1, 1, new DateTime(2012, 01, 01), "A", provider, ref ChipType, ref ErrorMessage);
Assert.AreNotEqual("", ErrorMessage);
Assert.AreEqual(0, result.Count);
}
[Test]
public void EmptyOrderedData_ReturnsErrorAndEmptyList()
{
FakeShipmentCalculator sc = new FakeShipmentCalculator();
string ErrorMessage = "";
string ChipType = "";
FakeDataProvier provider = new FakeDataProvier(new List<ShipmentInformation>() { new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" } });
List<ShipmentInformation> result = sc.GetBoxRange(1, 1, new DateTime(2012, 01, 01), "A", provider, ref ChipType, ref ErrorMessage);
Assert.AreNotEqual("", ErrorMessage);
Assert.AreEqual(0, result.Count);
}
}
//Integration test
[TestFixture]
public class GetDataMethod
{
}
[TestFixture]
public class GetSequentialBoxes
{
private StringCalculator CreateNewCalculator()
{
return new StringCalculator();
}
[Test]
public void MethodCalled_DoesntReturnNull()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> result = sc.GetSequentialBoxes(new List<ShipmentInformation>(), 100, 1);
Assert.IsNotNull(result);
}
[Test]
public void EmptyDataPassedIn_ReturnsEmptyData()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> result = sc.GetSequentialBoxes(new List<ShipmentInformation>(), 100, 1);
Assert.AreEqual(0, result.Count);
}
[Test]
public void OrderedData_ReturnsOrderedData()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> inputData = new List<ShipmentInformation>();
ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
data = new ShipmentInformation() { ChipType = "A", StartPP = 3, EndPP = 4, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, 2, 1);
ShipmentInformation firstItem = result.FirstOrDefault();
ShipmentInformation secondItem = result.LastOrDefault();
Assert.IsTrue(firstItem.StartPP == 1 && secondItem.StartPP == 3);
}
[Test]
public void UnOrderedData_ReturnsEmptyData()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> inputData = new List<ShipmentInformation>();
ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 3, EndPP = 4, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
int NUMBER_GREATER_THAN_ONE = 2;
List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, NUMBER_GREATER_THAN_ONE, 1);
Assert.AreEqual(0, result.Count);
}
[Test]
public void SequenceJumps_ClearsListAndStartsAgain()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> inputData = new List<ShipmentInformation>();
ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
data = new ShipmentInformation() { ChipType = "A", StartPP = 5, EndPP = 6, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, 2, 1);
Assert.IsTrue(result.First().StartPP == 5);
}
[Test]
public void LargestNumberOfItemsWithSameChipType_ReturnsDataWithOnlyThatChipType()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> inputData = new List<ShipmentInformation>();
ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
data = new ShipmentInformation() { ChipType = "A", StartPP = 3, EndPP = 4, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
data = new ShipmentInformation() { ChipType = "B", StartPP = 5, EndPP = 6, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
int BoxSizeSlashSequenceJumpAllowed = 2;
List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, BoxSizeSlashSequenceJumpAllowed, 1);
Assert.IsTrue(result.All(x => x.ChipType == "A"));
}
[Test]
public void TotalNumberOfRecordsPerChipTypeLessThanQuantity_ReturnsEmptyData()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> inputData = new List<ShipmentInformation>();
ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
data = new ShipmentInformation() { ChipType = "A", StartPP = 3, EndPP = 4, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
data = new ShipmentInformation() { ChipType = "B", StartPP = 5, EndPP = 6, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
int BoxSizeSlashSequenceJumpAllowed = 2;
int Quantity = 5;
List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, BoxSizeSlashSequenceJumpAllowed, Quantity);
Assert.AreEqual(0, result.Count);
}
[Test]
public void DataReturned_WhenQuantityReached()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> inputData = new List<ShipmentInformation>();
ShipmentInformation data = new ShipmentInformation() { ChipType = "A", StartPP = 1, EndPP = 2, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
data = new ShipmentInformation() { ChipType = "A", StartPP = 3, EndPP = 4, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
data = new ShipmentInformation() { ChipType = "A", StartPP = 5, EndPP = 6, JacketNo = "A", ReqNo = "B" };
inputData.Add(data);
int BoxSizeSlashSequenceJumpAllowed = 2;
int Quantity = 4;
List<ShipmentInformation> result = sc.GetSequentialBoxes(inputData, BoxSizeSlashSequenceJumpAllowed, Quantity);
Assert.AreEqual(2, result.Count);
}
}
[TestFixture]
public class GetRecordsPerGenre
{
private StringCalculator CreateNewCalculator()
{
return new StringCalculator();
}
[Test]
public void MethodCalled_DoesntReturnNull()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> result = sc.GetRecordsPerSerialRange(new List<ShipmentInformation>());
Assert.IsNotNull(result);
}
[Test]
public void EmptyDataPassedIn_ReturnsEmptyData()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> result = sc.GetRecordsPerSerialRange(new List<ShipmentInformation>());
Assert.AreEqual(0, result.Count);
}
[Test]
public void Data_ReturnsGroupedByData()
{
StringCalculator sc = CreateNewCalculator();
List<ShipmentInformation> inputData = new List<ShipmentInformation>();
ShipmentInformation data = new ShipmentInformation();
data.ChipType = "A";
data.ReqNo = "B";
data.JacketNo="C";
data.StartPP = 1;
data.EndPP = 2;
inputData.Add(data);
data = new ShipmentInformation();
data.ChipType = "A";
data.ReqNo = "B";
data.JacketNo = "C";
data.StartPP = 1;
data.EndPP = 2;
inputData.Add(data);
List<ShipmentInformation> result = sc.GetRecordsPerSerialRange(inputData);
Assert.AreEqual(1, result.Count);
}
}
At Jon, you may be biting off too much for a noob. implement TDD with a new feature, not an existing one. With this scenario, not only are you introducing testing, TDD, mocking. but now you have also introduced refactoring (yet another new concept).
once you have the the basics of TDD on greenfield code, you can then apply it brownfield code along with refactoring.
one last note: TDD doesn't require mocking, mocking is a separate concept that plays well with TDD, but it's not required. TDD, simply put: is driving out design through tests.
In order to unit test effectively you should adhere to some design principles. Loose coupling, Separation of concerns and Dependency Injection. The reason for this is, without, you will not be able to use mocks in your tests (which is what you will need to do)
I noticed in the first method in you above code you had:
//Get Connection String
//Do Database Queries and return shipmentInfo variable as List<ShipmentInformation>
I presume from this that you actually instantiate everything you need here to query the DB. This is not best practice and probably the root of your problems. You should be depending on abstractions and not concretions. A instance of a 'repository' interface (or similar) should be passed using Constructor injection.
A good book to get you started would be this: http://www.amazon.co.uk/Professional-ASP-NET-Design-Patterns-Millett/dp/0470292784
Hope this helps.
I'm using DevExpress for WinForms (the free one) and I'm using a 3D pie chart.
I already have a chart using the Windows version and all I do is pass four variables as the values the chart needs in the series.
Here's the code I use currently.
double[] yValues = { bottom, bmid, tmid, top};
string[] xNames = { "Greater than 200", "Between 200-100", "Between 100-50", "Below 50" };
chart1.Series[0].Points.DataBindXY(xNames, yValues);
Now, I've made a DevExpress chart and tried to use:
Devchart1.series[0].points
but points.databind does not exist.
Does anyone know how I bind the data like I have using WinForms?
UPDATE
Here's some more things I tried (commented out).
double[] yValues = { bottom, bmid, tmid, top};
string[] xNames = { "Greater than 200", "Between 200-100", "Between 100-50", "Below 50" };
chart1.Series[0].Points.DataBindXY(xNames, yValues);
DataTable chartTable = new DataTable("Table1");
// Add two columns to the table.
chartTable.Columns.Add("Names", typeof(string));
chartTable.Columns.Add("Value", typeof(Int32));
chartTable.Rows.Add("Below 50", top);
chartTable.Rows.Add("Between 50-100", tmid);
chartTable.Rows.Add("Between 100-200", bmid);
chartTable.Rows.Add("Greater than 200", top);
Series series1 = new Series("Series1", ViewType.Pie3D);
chartControl2.Series.Add(series1);
series1.DataSource = chartTable;
series1.ArgumentScaleType = ScaleType.Qualitative;
series1.ArgumentDataMember = "names";
series1.ValueScaleType = ScaleType.Numerical;
series1.ValueDataMembers.AddRange(new string[] { "Value" });
//((Pie3DSeriesView)series1.View). = true;
//((pie)chartControl2.Diagram).AxisY.Visible = false;
chartControl2.Legend.Visible = false;
// Dock the chart into its parent and add it to the current form.
chart1.Dock = DockStyle.Fill;
::UPDATE2::
heres what happens with this code with values 101, 22, 20 and 15.
DevExpress Series has DataSource property for binding.
Check this article. Hope it helps
UPDATE:
I use your code and it seems to work fine
DataTable chartTable = new DataTable("Table1");
// Add two columns to the table.
chartTable.Columns.Add("Names", typeof(string));
chartTable.Columns.Add("Value", typeof(Int32));
chartTable.Rows.Add("Below 50", 10);
chartTable.Rows.Add("Between 50-100", 10);
chartTable.Rows.Add("Between 100-200", 10);
chartTable.Rows.Add("Greater than 200", 10);
Series series1 = new Series("Series1", ViewType.Pie3D);
//chartControl1.Series.Clear();
chartControl2.Series.Add(series1);
series1.DataSource = chartTable;
series1.ArgumentScaleType = ScaleType.Qualitative;
series1.ArgumentDataMember = "names";
series1.ValueScaleType = ScaleType.Numerical;
series1.ValueDataMembers.AddRange(new string[] { "Value" });
//((Pie3DSeriesView)series1.View). = true;
//((pie)chartControl2.Diagram).AxisY.Visible = false;
chartControl2.Legend.Visible = false;