I have the following function which works fine and produces the results when their is one table selected. But when there is two tables being selected my _newList function is just replacing the fields in the array I will show you in graphical form best i can.
private void genXmlSchema_Click(object sender, EventArgs e)
{
List<TableDefnition> _newList = new List<TableDefnition>();
PersistentObject _testObjects = new PersistentObject();
List<GridViewRowInfo> _checkRows = GetCheckedRows(rgTableNames);
List<PersistentObject> _testObjectsList = new List<PersistentObject>();
foreach (GridViewRowInfo row in _checkRows)
{
var currentRow = (TableNames)row.DataBoundItem;
_newList = db.GetALLTableDeiniations(currentRow.TABLE_NAME);
rgFieldsOfTable.DataSource = db.GetALLTableDeiniations(currentRow.TABLE_NAME);
_testObjectsList.Add( BuildSchema(_newList, currentRow.TABLE_NAME));
}
_newPObject.PersistentObjects.AddRange(_testObjectsList);
_newPObject.ClassPrefix = "Persistent";
_newPObject.ClassSuffix = "";
_newPObject.Language = "VB";
_newPObject.Path = #"C:\Sage200SchemaExtensions";
_newPObject.GenerateSeparateFiles = "false";
_newPObject.GenerateBusinessObjects = "false";
_newPObject.BaselineSchema = #"C:\Program Files (x86)\Sage 200 SDK\SageObjectStore.xml";
_newPObject.DataTypes = "";
_newPObject.Enumerations = "";
_newPObject.MemberVariablePrefix = "_";
_newPObject.ApplicationNamespace = "BusinessObjects";
schemeContent.Text = HelperXml.ToXML(_newPObject);
}
On the second pass you will that it has duplicated the second table in both of the lists.
First Array Number after second pass
Second Array Number after second pass
As you can clearly see its lost the reference to the first table with 4 columns completely I no its something simple to do with my list creation and destruction but cant figure it out
Related
When my form is loaded, a query is run to get all employee records from SQL. Dapper compiles everything, and I put the contents in a List. My DataGridView table is bound to that list. I have a click event that retrieves the EmployeeID from the first column. Now, how do I sort through the List for the EmployeeModel with the matching ID without repeating the query? I will use this to bind other listboxes with the properties of that EmployeeModel. My first thought was to make the Form_Load method public and have it return employeeList, but it's an async method, and I don't know how to handle that. Would that be the right approach? Is the answer altogether different?
EDIT: I just noticed the first two lines are copied and pasted from my inventory initialization. They should read:
var employeeList = await InitializeEmployeeList();
EmployeeGridView.DataSource = employeeList;
public async void Dash_Load(object sender, System.EventArgs e)
{
var inventoryList = await InitializeInventoryList();
InventoryGridView.DataSource = inventoryList;
//Initialize Employee List
var employeeList = await InitializeEmployeeList();
EmployeeGridView.AutoGenerateColumns = false;
EmployeeGridView.ColumnCount=9;
EmployeeGridView.AutoSize = true;
EmployeeGridView.DataSource = employeeList;
EmployeeGridView.Columns[0].HeaderText = "Employee ID";
EmployeeGridView.Columns[0].DataPropertyName = "ID";
EmployeeGridView.Columns[1].HeaderText = "First Name";
EmployeeGridView.Columns[1].DataPropertyName = "FirstName";
EmployeeGridView.Columns[2].HeaderText = "Last Name";
EmployeeGridView.Columns[2].DataPropertyName = "LastName";
EmployeeGridView.Columns[3].HeaderText = "Nickname";
EmployeeGridView.Columns[3].DataPropertyName = "Nickname";
EmployeeGridView.Columns[4].HeaderText = "JobTitle";
EmployeeGridView.Columns[4].DataPropertyName = "JobTitle";
EmployeeGridView.Columns[5].HeaderText = "Forklift";
EmployeeGridView.Columns[5].DataPropertyName = "ForkliftCert";
EmployeeGridView.Columns[6].HeaderText = "AWP";
EmployeeGridView.Columns[6].DataPropertyName = "AWPCert";
EmployeeGridView.Columns[7].HeaderText = "Confined Space";
EmployeeGridView.Columns[7].DataPropertyName = "ConfinedSpaceCert";
EmployeeGridView.Columns[8].HeaderText = "NFPA51b";
EmployeeGridView.Columns[8].DataPropertyName = "NFPA51bCert";
}
{
DataGridViewCell selectedEmployeeCell = EmployeeGridView.CurrentCell;
int selectedEmployeeRow = selectedEmployeeCell.RowIndex;
string selectedEmployeeID = EmployeeGridView.Rows[selectedEmployeeRow].Cells[0].Value.ToString();
}
put a global
public static InvertoryList lst;
after getting data from your method
fill it with your data
if(lst==null)lst=new InvertoryList();
lst=your inventoryList;
then you can reach lst from everywhere in your form.
I have a combobox in my WinForms application in which you can search for a string and results are filtered accordingly, but it seems to behave very strangely. I am searching for "Coo" and I get a very long list of products that do not contain the string "coo" (http://prntscr.com/pr54rs). However, when I type in "coor" and then press backspace, leaving me with "coo" again, the list of results is different (http://prntscr.com/pr55ef)
I am using the "KeyPress" event handler to search in the combobox. The code looks like this
private void comboBox1_KeyPress(object sender, KeyPressEventArgs e)
{
comboBox1.Items.Clear();
listNew.Clear();
var source = new AutoCompleteStringCollection();
foreach (var item in listOnit)
{
if (item.ToLower().Contains(this.comboBox1.Text.ToLower()))
{
listNew.Add(item);
}
}
comboBox1.Items.AddRange(listNew.ToArray());
comboBox1.SelectionStart = this.comboBox1.Text.Length;
Cursor = Cursors.Default;
comboBox1.DroppedDown = true;
}
Am I doing something wrong? The list is populated from a database
string sqlProducts = "SELECT Description FROM stocktake_products WHERE stocktake_id = '" + stocktakeID.stocktake_id + "' AND (PLUProdCode IS NULL OR PLUProdCode = '');";
MySqlCommand cmdProduct = new MySqlCommand(sqlProducts, conn);
cmdProduct.CommandTimeout = 10000;
MySqlDataReader rdrProduct = cmdProduct.ExecuteReader();
AutoCompleteStringCollection myCollectionSales1 = new AutoCompleteStringCollection();
if (rdrProduct.HasRows == true)
{
while (rdrProduct.Read())
{
// myCollectionSales1.Add(rdrProduct[0].ToString());
listOnit.Add(rdrProduct[0].ToString());
}
rdrProduct.Close();
//textBox1.AutoCompleteCustomSource = myCollectionSales1;
comboBox1.Items.AddRange(listOnit.ToArray());
}
I want the combobox to only display results that contain the whole string that has been typed in, not every phrase that has typed letters in any position as it seems like that's what it is doing.
I have tried to include the BeginIvoke method (not sure if done correctly thought as I have never used it before)
this.BeginInvoke((MethodInvoker)delegate
{
comboBox1.Items.Clear();
listNew.Clear();
var source = new AutoCompleteStringCollection();
foreach (var item in listOnit)
{
if (item.ToLower().Contains(this.comboBox1.Text.ToLower()))
{
listNew.Add(item);
}
}
comboBox1.Items.AddRange(listNew.ToArray());
comboBox1.SelectionStart = this.comboBox1.Text.Length;
Cursor = Cursors.Default;
comboBox1.DroppedDown = true;
});
Now when I start typing the first character, the combobox selects to top result right away (http://prntscr.com/pr5f6i). I have to press the first character again and then type the rest of the string to be able to actually search through the list.
My current code works and output is correct. I am pulling data from a data.txt file and have successfully done so to an array using TextFieldParser. Is there a way to convert my code to a List? And how so? If converting is not an option then any recommendations on where to start with the code? Basically trying to go from an array to a list collections.
public partial class EmployeeInfoGeneratorForm : Form
{
public EmployeeInfoGeneratorForm()
{
InitializeComponent();
}
// button event handler
private void GenerateButton_Click(object sender, EventArgs e)
{
string[] parts;
if(File.Exists("..\\data.txt"))
{
TextFieldParser parser = new TextFieldParser("..\\data.txt");
parser.Delimiters = new string[] { "," };
while (true)
{
parts = parser.ReadFields();
if (parts == null)
{
break;
}
this.nameheadtxt.Text = parts[0];
this.addressheadtxt.Text = parts[1];
this.ageheadtxt.Text = parts[2];
this.payheadtxt.Text = parts[3];
this.idheadtxt.Text = parts[4];
this.devtypeheadtxt.Text = parts[5];
this.taxheadtxt.Text = parts[6];
this.emp1nametxt.Text = parts[7];
this.emp1addresstxt.Text = parts[8];
this.emp1agetxt.Text = parts[9];
this.emp1paytxt.Text = parts[10];
this.emp1idtxt.Text = parts[11];
this.emp1typetxt.Text = parts[12];
this.emp1taxtxt.Text = parts[13];
this.emp2nametxt.Text = parts[14];
this.emp2addresstxt.Text = parts[15];
this.emp2agetxt.Text = parts[16];
this.emp2paytxt.Text = parts[17];
this.emp2idtxt.Text = parts[18];
this.emp2typetxt.Text = parts[19];
this.emp2taxtxt.Text = parts[20];
this.emp3nametxt.Text = parts[21];
this.emp3addresstxt.Text = parts[22];
this.emp3agetxt.Text = parts[23];
this.emp3paytxt.Text = parts[24];
this.emp3idtxt.Text = parts[25];
this.emp3typetxt.Text = parts[26];
this.emp3taxtxt.Text = parts[27];
}
}
else //Error Message for if File isn't found
{
lblError.Text = "File Not Found";
}
}
}
In your code example there are two arrays.
First example
parser.Delimiters = new string[] { "," };
Since parser is a TextFieldParser, I can see that Delimiters must be set to a string array. So you cannot change it.
Second example
string[] parts;
parts = parser.ReadFields();
This array accepts the result of parser.ReadFields(). The output of that function is a string array, so this code can't be changed without breaking the call.
However, you can immediately convert it to a list afterward:
var parts = parser.ReadFields().ToList();
There isn't much point to this either.
An array is just as good as a list when the size of the array/list doesn't change after it is created. Making it into a list will just add overhead.
There are a number of problems here. I'd be inclined to write your code like this:
public static IEnumerable<List<string>> ParseFields(string file)
{
// Use "using" to clean up the parser.
using (var parser = new TextFieldParser(file))
{
parser.Delimiters = new string[] { "," };
// Use end-of-data, not checks for null.
while (!parser.EndOfData)
yield return parser.ReadFields().ToList();
}
}
I'd refactor your code to put the UI updates in one method:
private void UpdateText(List<string> parts ) { ... }
You only do something with the last element in the sequence; all your previous edits are lost. So be explicit about that:
private void GenerateButton_Click(object sender, EventArgs e)
{
// Use a named constant for constant strings used in several places
const string data = "..\\data.txt";
if(!File.Exists(data))
{
lblError.Text = "File Not Found";
} else {
var parts = ParseFields(data).LastOrDefault();
if (parts != null)
UpdateText(parts);
}
}
See how much cleaner that logic looks when you break it up into smaller parts? It's very pleasant to have methods that fit easily onto a page.
A direct answer to your question:
Use the List<T> constructor that takes an IEnumerable<T> parameter.
With that said, I would read Mr. Lippert's answer until you fully understand it.
first of all there is a searchbox form and a view form. after passing the value of the id in the searchbox, it should return all the values that matches with the id of that person after the textchange method occured. but it doesn't display a single value on the textboxes. here is my code
public void first_tab_search(string key)
{
key = txtSearch.Text;
var first = from a in dbcon.personal_informations where a.last_name == key select a;
foreach (var setThem in first)
{
txtsurname.Text = setThem.last_name;
txtfirstname.Text = setThem.first_name;
txtmiddlename.Text = setThem.middle_name;
txtID.Text = setThem.userid;
txtweight.Text = setThem.weight;
txttin.Text = setThem.tin;
txtsss.Text = setThem.sss;
txtaeno.Text = setThem.agency_employee_no;
txtbloodtype.Text = setThem.blood_type;
txtcitizenship.Text = setThem.citizenship;
txtcivilstatus.Text = setThem.civil_status;
txtcpno.Text = setThem.cell_no;
txtdob.Text = setThem.datetime_of_birth.ToString();
txtemail.Text = setThem.email_address;
txtgender.Text = setThem.sex;
txtgsis.Text = setThem.gsis_id;
txtheight.Text = setThem.height;
txtnameext.Text = setThem.name_ext;
txtpagibig.Text = setThem.pagibig_id;
txtpermaaddr.Text = setThem.permanent_address;
txtpermatelno.Text = setThem.permanent_telno;
txtpermazip.Text = setThem.permanent_zipcode;
txtphilhealth.Text = setThem.philhealth;
txtpob.Text = setThem.place_of_birth;
txtresidentialaddr.Text = setThem.residential_address;
txtresitelno.Text = setThem.residential_telno;
txtresizip.Text = setThem.residential_zipcode;
txtweight.Text = setThem.weight;
}
}
You have a whole host of problems going on here.
You pass a key into the method, and then immediately overwrite it with the contents of your search box.
Your search could return more than one result, and therefore your code is looping through each result and overwriting the output values with the last returned row. Use += rather than + in your loop, i.e.
txtsurname.Text += setThem.last_name;
Your code is currently case sensitive, this may be the desired approach but might not be.
I'm trying to get back 2 unique images form an array. Right now I'm refreshing the page until I get 2 unique images. This is not ideal. How can I modify this code to back 2 unique images with out refreshing the page till it hapens.
Can I do it in this layer or do I need to check for unique numbers in the data layer?
Picture dlPicture = new Picture();
DataTable DTPictures = dlPicture.GetRandomPicture();
Picture dlPicture2 = new Picture();
DataTable DTPictures2 = dlPicture2.GetRandomPicture();
// the variables to hold the yes and no Id's for each set
string firstNoPicId = "";
string firstYesPicId = "";
string secondNoPicId = "";
string secondYesPicId = "";
foreach (DataRow row in DTPictures.Rows)
{
firstYesPicId = row["PicID"].ToString();
secondNoPicId = firstYesPicId;
FirstPicMemberNameLabel.Text = row["MemberName"].ToString();
FirstPicLink.ImageUrl = "Pictures/" + row["PicLoc"];
}
foreach (DataRow row in DTPictures2.Rows)
{
secondYesPicId = row["PicID"].ToString();
firstNoPicId = secondYesPicId;
SecondPicMemberNameLabel.Text = row["MemberName"].ToString();
SecondPicLink.ImageUrl = "Pictures/" + row["PicLoc"];
}
if (firstYesPicId != secondYesPicId)
{
FirstPicLink.PostBackUrl = "default.aspx?yesId=" + firstYesPicId + "&noId=" + firstNoPicId;
SecondPicLink.PostBackUrl = "default.aspx?yesId=" + secondYesPicId + "&noId=" + secondNoPicId;
}
else
{
Response.Redirect("Default.aspx");
}
There two pretty obvious ways to deal with this
Add an overload dlPicture.GetRandomPicture(int picID) This will accept an ID so that it won't return an already used picID
restructure your code so that it loops until the secondYesPicId != firstYesPicId
Something like
secondYesPicId = firstYesPicId;
while (firstYesPicId == secondYesPicId)
{ DataTable DTPictures2 = dlPicture2.GetRandomPicture();
foreach (DataRow row in DTPictures2.Rows)
{
secondYesPicId = row["PicID"].ToString();
SecondPicMemberNameLabel.Text = row["MemberName"].ToString();
SecondPicLink.ImageUrl = "Pictures/" + row["PicLoc"];
}
}
Perhaps a better solution would be adding code to your datalayer.GetRandomPicture to make sure it can't return the same picture twice in a row?
in this Picture class add a LastRandomPictureID variable and do a 'WHERE NOT ID = LastRandomPictureID' on your query (you might want to make it a bit more robust to handle the case where only 1 picture exists).
var rnd = new Random();
int randomPicIndex1 = rnd.Next(numOfPictures);
int randomPicIndex2;
do {
randomPicIndex2 = rnd.Next(numOfPictures);
} while (randomPicIndex1 == randomPicIndex2);
Then use these indexes in order to get random rows from your table.
DataRow row1 = DTPictures.Rows[randomPicIndex1];
DataRow row2 = DTPictures.Rows[randomPicIndex2];