C# Observable Collection LDAP Paths Children for WPF TreeView - c#

I'm hoping someone can help. A long time windows forms/aspx user, moving to WPF.
Not expecting a coded answer to this, but any pointers on a different way to approach would be greatly appreciated - I am probably approaching this in a very backward way.
So the objective is to have an ObservableCollection with sub ObservableCollection "childen" within to then bind to my WPF treeview control.
I can bind my collection to the treeview without issues, and have styled it with checkboxes images as desired, frustratingly, its the ObservableCollection with children of children of children I am having trouble generating in the first place.
I have a table in SQL with LDAP Paths, and various other information I'm storing against that LDAP path, which I read into my ObservableCollection.
Single level, no problem, the bit I'm struggling with is sorted the sub objects of sub objects by LDAP Path, so when I bind to the treeview is presented as AD OU's are structured.
EG:
TopOU
Users
Front Office Users
Helpdesk Users
Example LDAP Paths in my DB
LDAP://OU=Front Office Users,OU=Users,OU=TopOU,DC=dev,DC=local
LDAP://OU=Helpdesk Users,OU=Users,OU=TopOU,DC=dev,DC=local
LDAP://OU=OU=Users,OU=TopOU,DC=dev,DC=local
LDAP://OU=OU=TopOU,DC=dev,DC=local
private ObservableCollection<AssignmentData> OUTreeAssignmentsCollection = new ObservableCollection<AssignmentData>();
public class AssignmentData : INotifyPropertyChanged
{
public Int32 AssignmentID { get; set; }
public String AssignmentName { get; set; }
public AssignmentTypes AssignmentType { get; set; }
//other stuff....
//For TreeView all sub nodes
public ObservableCollection<AssignmentData> Children { get; set; }
}
I then start to read from my db in a rather nasty way, and this is where it all goes wrong, and I could use some pointers.
cmd = new SqlCommand("SELECT UserGroups.UserGroupID, UserGroups.Name, UserGroups.LDAPPath FROM UserGroups WHERE UserGroups.TypeID=1", DBCon);
reader = cmd.ExecuteReader();
while (reader.Read())
{
String strLDAPHierarchical = GetLDAPHierarchical(reader[2].ToString());
AssignmentData newItem = new AssignmentData()
{
AssignmentID = Convert.ToInt32(reader[0]),
AssignmentName = reader[1].ToString(),
AssignmentImage = ouIcon,
AssignmentLDAPPath = reader[2].ToString(),
AssignmentCNPath = GetCNFromLDAPPath(reader[2].ToString()),
AssignmentTooltip = GetADSLocationTooltip(reader[2].ToString()),
AssignmentType = AssignmentTypes.UserOU,
AssignmentLDAPHierarchical = strLDAPHierarchical
};
if (strLDAPHierarchical.Contains(","))
{
//Now check all the root nodes exist to continue
String strLDAPHierarchicalCheckPath = strLDAPHierarchical;
String[] SplitLDAPHierarchical = strLDAPHierarchical.Split(new Char[] { ',' });
Int32 reverseI = SplitLDAPHierarchical.Length - 1;
String prevPath = "";
for (int i = 0; i < SplitLDAPHierarchical.Length; i++)
{
String path = SplitLDAPHierarchical[reverseI];
//now check if this node is already there and if not look it up and create it
if (path != "")
{
if (i == 0) { strLDAPHierarchicalCheckPath = path; }
else { strLDAPHierarchicalCheckPath = path + "," + prevPath; }
WriteLog("CHECK:" + strLDAPHierarchicalCheckPath);
LookupItemByLDAPHierarchical(strLDAPHierarchicalCheckPath, newItem);
if (i == 0) { prevPath = path; }
else { prevPath = path + "," + prevPath; }
reverseI = reverseI - 1;
}
}
}
else
{
//is top level object, so create at the root of the collection
UserOUCollection.Add(newItem);
}
Function to add sub items :-/
internal AssignmentData LookupItemByLDAPHierarchical(String strLDAPHierarchical, AssignmentData fromItem)
{
AssignmentData currentItem = null;
foreach (AssignmentData d in UserOUCollection)
{
if (d.AssignmentLDAPHierarchical == strLDAPHierarchical) { currentItem = d; break; }
if (d.Children != null)
{
currentItem = CheckChildNodesByLDAPHierarchical(d, strLDAPHierarchical);
if (currentItem != null) { break; }
}
}
String strMessage = "null";
if (currentItem != null) { strMessage = currentItem.AssignmentLDAPPath; }
if (currentItem == null)
{
String strWhere = "LDAPPath LIKE 'LDAP://" + strLDAPHierarchical + "%'";
SqlConnection DBCon = new SqlConnection(SQLString);
DBCon.Open();
SqlCommand cmd = new SqlCommand("SELECT UserGroupID, Name, LDAPPath FROM UserGroups WHERE " + strWhere + " AND TypeID=1", DBCon);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
strLDAPHierarchical = GetLDAPHierarchical(reader[2].ToString());
AssignmentData newItem = new AssignmentData()
{
AssignmentID = Convert.ToInt32(reader[0]),
AssignmentName = reader[1].ToString(),
AssignmentImage = ouIcon,
AssignmentLDAPPath = reader[2].ToString(),
AssignmentCNPath = GetCNFromLDAPPath(reader[2].ToString()),
AssignmentTooltip = GetADSLocationTooltip(reader[2].ToString()),
AssignmentType = AssignmentTypes.UserOU,
AssignmentLDAPHierarchical = strLDAPHierarchical
};
String strLDAPHierarchicalCheckPath = strLDAPHierarchical;
foreach (String path in strLDAPHierarchical.Split(new Char[] { ',' }))
{
//now check if this node is already there and if not look it up and create it
if (path != "")
{
strLDAPHierarchicalCheckPath = strLDAPHierarchicalCheckPath.Replace(path + ",", "");
currentItem = LookupItemByLDAPHierarchical(strLDAPHierarchicalCheckPath, currentItem);
if (null == currentItem)
{
UserOUCollection.Add(newItem); //new root item
}
else
{
if (currentItem.Children == null)
{
//add new child
currentItem.Children = new ObservableCollection<AssignmentData> { newItem };
}
else
{
//add more children to exisiting
currentItem.Children.Add(newItem);
}
}
currentItem = null;
}
}
//Find a current Item to add the node to
//currentItem = LookupItemByLDAPHierarchical(strLDAPHierarchical);
}
reader.Close();
reader.Dispose();
DBCon.Close();
DBCon.Dispose();
}
return currentItem;
}
With my current solution, I get a treeview, with sub nodes of sub nodes, but they are wrong/lots of duplication etc. I have spent literally days trying to fix my probably overcomplicated attempt above - but have come to the conclusion I'm probably going about it the wrong way.
Any help greatly appreciated!

Just having a peruse ;) through your code. Think I can see why you have lots of duplications. Looks like your first SQL query get's all parent/child records. Then the second query will go and get some of those records again, if that makes sense.
One approach would be to only get the top level items in your first query. Possibly by getting SQL to count the number of commas.
SELECT UserGroups.UserGroupID, UserGroups.Name, UserGroups.LDAPPath,
LENGTH(LDAPPath) - LENGTH(REPLACE(LDAPPath, ',', '')) as CommaCount
FROM UserGroups
WHERE UserGroups.TypeID=1
AND CommaCount = 2
Since you asked for different approach id say it's not very efficient to repeatedly query the database in a loop. When I'm building a tree of parent child objects I'd normally get all parent/child records in one query. Build a flat dictionary of all the objects. Then loop through it and make the parent/child associations.
The dictionary can also be useful to lookup your objects later on either directly by key or to loop through without having to make a recursive function that crawls the tree.
So I'd suggest that you break it down into 2 blocks of code.
First block: Using your existing query that get's all of the items, create a flat Dictionary with everything in.
They key of each item should probably be the result from GetLDAPHierarchical().
Second block: Next loop through the dictionary and create the hierarchy. Add anything with no parent directly to the UserOUCollection
foreach(AssignmentData d in myDictionary.Values)
{
String parentKey = GetParentLDAPKey(d.AssignmentLDAPHierarchical);
if (myDictionary.ContainsKey(parentKey))
{
myDictionary(parentKey).children.Add(d);
}
else
{
UserOUCollection.Add(d);
}
}
GetParentLDAPKey() will need to produce the same key as it's parent by removing the first part of the LDAP Path.
Hope that points you in the right direction.
H
(SMASH)

Thanks so much to hman, who pointed me in a much more logical direction. I used LDAPPath as my dictionary key.
Dictionary<String, AssignmentData> OUDictionary = new Dictionary<String, AssignmentData>();
//Read from DB
cmd = new SqlCommand("SELECT UserGroups.UserGroupID, UserGroups.Name, UserGroups.LDAPPath FROM UserGroups WHERE UserGroups.TypeID=1", DBCon);
reader = cmd.ExecuteReader();
while (reader.Read())
{
AssignmentData newItem = new AssignmentData()
{
AssignmentID = Convert.ToInt32(reader[0]),
AssignmentName = reader[1].ToString(),
AssignmentImage = ouIcon,
AssignmentLDAPPath = reader[2].ToString(),
AssignmentCNPath = GetCNFromLDAPPath(reader[2].ToString()),
AssignmentTooltip = GetADSLocationTooltip(reader[2].ToString()),
AssignmentType = AssignmentTypes.UserOU,
};
UserOUDictionary.Add(reader[2].ToString(), newItem);
}
reader.Close();
reader.Dispose();
//Now Read OU List into TreeView Collection
foreach (AssignmentData d in UserOUDictionary.Values)
{
String parentKey = GetParentLDAPPath(d.AssignmentLDAPPath);
if (UserOUDictionary.ContainsKey(parentKey))
{
AssignmentData parentItem = UserOUDictionary[parentKey];
if (parentItem.Children == null) { parentItem.Children = new ObservableCollection<AssignmentData> { d }; } //add first child
else { parentItem.Children.Add(d); } //add more children to exisiting
}
else
{
UserOUCollection.Add(d); //add to root of control
}
}
private String GetParentLDAPKey(String strLDAPPath)
{
String retParentKey = strLDAPPath;
if (strLDAPPath.Contains(","))
{
retParentKey = retParentKey.Replace("LDAP://", "");
retParentKey = retParentKey.Remove(0, retParentKey.IndexOf(",") + 1);
retParentKey = "LDAP://" + retParentKey;
}
return retParentKey;
}

Related

Working with a ListBox from an SQL database

I'm new to CS. I have a ListBox control that I populate from an SQL table called Category. I have a class called Category to match the fields from the DB. I want all my fields available to edit and save. The ListBox has a single field, CategoryDesc. When I select an item in the ListBox I want two textboxes and a check box to update with the CategoryID (string), CategoryDesc (string), and IsActive (bool). I have it working but it seems cumbersome and like I'm taking a lot of steps. I want to learn efficient coding so I'm submitting the following for suggestions on how to clean it up and make it more efficient. Any positive comments will be greatly appreciated.
id ListControl()
{
this.LstCategory.SelectedIndexChanged -= new System.EventHandler(this.LstCategory_SelectedIndexChanged);
DataTable categoryDt = new DataTable();
categoryDt = GetDataTable("GetListCategory");
for (int i = 0; i < categoryDt.Rows.Count; i++)
{
category.Add(new Category()
{
CategoryID = (int)(categoryDt.Rows[i]["CategoryId"]),
CategoryDesc = (string)(categoryDt.Rows[i]["CategoryDesc"]),
ShortCode = (string)(categoryDt.Rows[i]["ShortCode"]),
IsActive = (bool)(categoryDt.Rows[i]["IsActive"]),
CanDelete = (bool)(categoryDt.Rows[i]["CanDelete"])
});
LstCategory.Items.Add((string)(categoryDt.Rows[i]["CategoryDesc"]));
}
this.LstCategory.SelectedIndexChanged += new System.EventHandler(this.LstCategory_SelectedIndexChanged);
}
private void LstCategory_SelectedIndexChanged(object sender, EventArgs e)
{
if (LstCategory.SelectedIndex >= 0)
{
string desc = LstCategory.SelectedItem.ToString();
foreach (var c in category)
{
if (c.CategoryDesc == desc)
{
TxtDescription.Text = c.CategoryDesc;
TxtShortCode.Text = c.ShortCode;
ChkIsActive.Checked = c.IsActive;
}
}
}
else
{
TxtDescription.Text = string.Empty;
TxtShortCode.Text = string.Empty;
ChkIsActive.Checked = false;
}
}
Thanks.
Learn to use Linq
This
categoryDt = GetDataTable("GetListCategory");
for (int i = 0; i < categoryDt.Rows.Count; i++)
{
category.Add(new Category()
{
CategoryID = (int)(categoryDt.Rows[i]["CategoryId"]),
CategoryDesc = (string)(categoryDt.Rows[i]["CategoryDesc"]),
ShortCode = (string)(categoryDt.Rows[i]["ShortCode"]),
IsActive = (bool)(categoryDt.Rows[i]["IsActive"]),
CanDelete = (bool)(categoryDt.Rows[i]["CanDelete"])
});
LstCategory.Items.Add((string)(categoryDt.Rows[i]["CategoryDesc"]));
}
can be replaced by
category = categoryDt.Select(cd => new Category{
CategoryID = (int)(cd["CategoryId"]),
CategoryDesc = (string)(cd[i]["CategoryDesc"]),
ShortCode = (string)(cd["ShortCode"]),
IsActive = (bool)(cd[i]["IsActive"]),
CanDelete = (bool)(cd[i]["CanDelete"])}).ToList();
LstCategory.Items.AddRange(category.Select(c=>c.Desc));
and
string desc = LstCategory.SelectedItem.ToString();
foreach (var c in category)
{
if (c.CategoryDesc == desc)
{
TxtDescription.Text = c.CategoryDesc;
TxtShortCode.Text = c.ShortCode;
ChkIsActive.Checked = c.IsActive;
}
}
can be replaced by
var c = category.FirstOrDefault(c=>c ==desc);
TxtDescription.Text = c.CategoryDesc;
TxtShortCode.Text = c.ShortCode;
ChkIsActive.Checked = c.IsActive;
There might be a few typos here and there becuase I dont have yur data structures to try it out on.
But LINQ is incredibly useful for performing operations on collections.
'select' is used to transform 'project' (its not a filter)
'where' is used to filter
'FindFirstOrDefault' will retunr the first match (or null)
'Count' counts
'ToList' converts to list
The nice thing is you can chain then together
mylist.Where(...).Select(..) etc

UWP - Compare data on JSON and database

I have a database called ebookstore.db as below:
and JSON as below:
I want when slug on JSON is not the same as a title in the database, it will display the amount of data with a slug on JSON which is not same as a title in the database in ukomikText.
Code:
string judulbuku;
try
{
string urlPath1 = "https://...";
var httpClient1 = new HttpClient(new HttpClientHandler());
httpClient1.DefaultRequestHeaders.TryAddWithoutValidation("KIAT-API-KEY", "....");
var values1 = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("halaman", 1),
new KeyValuePair<string, string>("limit", 100),
};
var response1 = await httpClient1.PostAsync(urlPath1, new FormUrlEncodedContent(values1));
response1.EnsureSuccessStatusCode();
if (!response1.IsSuccessStatusCode)
{
MessageDialog messageDialog = new MessageDialog("Memeriksa update Komik gagal", "Gangguan Server");
await messageDialog.ShowAsync();
}
string jsonText1 = await response1.Content.ReadAsStringAsync();
JsonObject jsonObject1 = JsonObject.Parse(jsonText1);
JsonArray jsonData1 = jsonObject1["data"].GetArray();
foreach (JsonValue groupValue in jsonData1)
{
JsonObject groupObject = groupValue.GetObject();
string id = groupObject["id"].GetString();
string judul = groupObject["judul"].GetString();
string slug = groupObject["slug"].GetString();
BukuUpdate file1 = new BukuUpdate();
file1.ID = id;
file1.Judul = judul;
file1.Slug = slug;
List<String> title = sqlhelp.GetKomikData();
foreach (string juduldb in title)
{
judulbuku = juduldb.Substring(juduldb.IndexOf('.') + 1);
if (judulbuku != file1.Slug.Replace("-", "_") + ".pdf")
{
BukuData.Add(file1);
ListBuku.ItemsSource = BukuData;
}
else
{
ukomikText.Text = "belum tersedia komik yang baru";
ukomikText.Visibility = Visibility.Visible;
}
}
}
if (ListBuku.Items.Count > 0)
{
ukomikText.Text = BukuData.Count + " komik baru";
ukomikText.Visibility = Visibility.Visible;
jumlahbuku = BukuData.Count;
}
else
{
ukomikText.Text = "belum tersedia komik yang baru";
ukomikText.Visibility = Visibility.Visible;
}
public static List<String> GetKomikData()
{
List<String> entries = new List<string>();
using (SqliteConnection db =
new SqliteConnection("Filename=ebookstore.db"))
{
db.Open();
SqliteCommand selectCommand = new SqliteCommand
("SELECT title FROM books where folder_id = 67", db);
SqliteDataReader query = selectCommand.ExecuteReader();
while (query.Read())
{
entries.Add(query.GetString(0));
}
db.Close();
}
return entries;
}
BukuUpdate.cs:
public string ID { get; set; }
public string Judul { get; set; }
public string Slug { get; set; }
I have a problem, that is when checking slugs on JSON, then the slug that is displayed is the first slug is displayed repeatedly as much data in the database, after that show the second slug repeatedly as much data on the database, and so on, as below:
How to solve it so that slug on JSON is not displayed repeatedly (according to the amount of data on JSON)?
The problem is that you have two nested foreach loops. What the code does in simplified pseudocode:
For each item in JSON
Load all rows from DB
And for each loaded row
Check if the current JSON item matches the row from DB and if not, output
As you can see, if you have N items in the JSON and M rows in the database, this inevitably leads to N*M lines of output except for those rare ones where the JSON item matches a specific row in database.
If I understand it correctly, I assume that you instead want to check if there is a row that matches the JSON item and if not, output it. You could do this the following way:
List<String> title = sqlhelp.GetKomikData();
HashSet<string> dbItems = new HashSet<string>();
foreach (string juduldb in title)
{
judulbuku = juduldb.Substring(juduldb.IndexOf('.') + 1);
dbItems.Add( judulbuku );
}
...
foreach ( JsonValue groupValue in jsonData1 )
{
...
//instead of the second foreach
if ( !dbItems.Contains( file1.Slug.Replace("-", "_") + ".pdf" ) )
{
//item is not in database
}
else
{
//item is in database
}
}
Additional tips
Avoid calling GetKomikData inside the foreach. This method does not have any arguments and that means you are just accessing the database again and again without a reason, which takes time and slows down the execution significantly. Instead, call GetKomikData only once before the first foreach and then just use title variable.
Don't assign ItemsSource every time the collection changes. This will unnecessarily slow down the UI thread, as it will have to reload all the items with each loop. Instead, assign the property only once after the outer foreach
write your code in one language. When you start mixing variable names in English with Indonesian, the code becomes confusing and less readable and adds cognitive overhead.
avoid non-descriptive variable names like file1 or jsonObject1. The variable name should be clear and tell you what it contains. When there is a number at the end, it usually means it could be named more clearly.
use plurals for list variable names - instead of title use titles

how to separate the "collection" from creating and adding a new instance of "lookaheadRunInfo"

I am trying to "collect" the GetString(2) until GetString(0) changes,so am trying to find out how to separate the "collection" from creating and adding a new instance of "lookaheadRunInfo"?I have tried as below which throws an exception
System.NullReferenceException was unhandled by user code at line
lookaheadRunInfo.gerrits.Add(rdr.GetString(1)); ,can anyone provide guidance on how to fix this issue?
try
{
Console.WriteLine("Connecting to MySQL...");
conn.Open();
string sql = #"select lr.ec_job_link, cl.change_list ,lr.submitted_by, lr.submission_time,lr.lookahead_run_status
from lookahead_run as lr, lookahead_run_change_list as lrcl, change_list_details as cld,change_lists as cl
where lr.lookahead_run_status is null
and lr.submission_time is not null
and lrcl.lookahead_run_id = lr.lookahead_run_id
and cl.change_list_id = lrcl.change_list_id
and cl.change_list_id not in (select clcl.change_list_id from component_labels_change_lists as clcl)
and cld.change_list_id = lrcl.change_list_id
group by lr.lookahead_run_id, cl.change_list
order by lr.submission_time desc
limit 1000
";
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
var ECJoblink_previous ="";
var gerritList = new List<String>();
while (rdr.Read())
{
//Console.WriteLine(rdr[0] + " -- " + rdr[1]);
//Console.ReadLine();
var lookaheadRunInfo = new LookaheadRunInfo();
lookaheadRunInfo.ECJobLink = rdr.GetString(0);
if (ECJoblink_previous == lookaheadRunInfo.ECJobLink)
{
//Keep appending the list of gerrits until we get a new lookaheadRunInfo.ECJobLink
lookaheadRunInfo.gerrits.Add(rdr.GetString(1));
}
else
{
lookaheadRunInfo.gerrits = new List<string> { rdr.GetString(1) };
}
ECJoblink_previous = lookaheadRunInfo.ECJobLink;
lookaheadRunInfo.UserSubmitted = rdr.GetString(2);
lookaheadRunInfo.SubmittedTime = rdr.GetString(3).ToString();
lookaheadRunInfo.RunStatus = "null";
lookaheadRunInfo.ElapsedTime = (DateTime.UtcNow-rdr.GetDateTime(3)).ToString();
lookaheadRunsInfo.Add(lookaheadRunInfo);
}
rdr.Close();
}
catch
{
throw;
}
If I understand your requirements correctly, you wish to keep a single lookaheadRunInfo for several rows of the resultset, until GetString(0) changes. Is that right?
In that case you have some significant logic problems. The way it is written, even if we fix the null reference, you will get a new lookaheadRunInfo with each and every row.
Try this:
string ECJoblink_previous = null;
LookAheadRunInfo lookaheadRunInfo = null;
while (rdr.Read())
{
if (ECJoblink_previous != rdr.GetString(0)) //A new set of rows is starting
{
if (lookaheadRunInfo != null)
{
lookaheadRunsInfo.Add(lookaheadRunInfo); //Save the old group, if it exists
}
lookaheadRunInfo = new LookAheadRunInfo //Start a new group and initialize it
{
ECJobLink = rdr.GetString(0),
gerrits = new List<string>(),
UserSubmitted = rdr.GetString(2),
SubmittedTime = rdr.GetString(3).ToString(),
RunStatus = "null",
ElapsedTime = (DateTime.UtcNow-rdr.GetDateTime(3)).ToString()
}
}
lookahead.gerrits.Add(rdr.GetString(1)); //Add current row
ECJoblink_previous = rdr.GetString(0); //Keep track of column 0 for next iteration
}
if (lookaheadRunInfo != null)
{
lookaheadRunsInfo.Add(lookaheadRunInfo); //Save the last group, if there is one
}
The idea here is:
Start with a blank slate, nothing initialized
Monitor column 0. When it changes (as it will on the first row), save any old list and start a new one
Add to current list with each and every iteration
When done, save any remaining items in its own list. A null check is required in case the reader returned 0 rows.

Grouping Data from a text file in C#

I am currently working on a small project that returns text from 'txt' file based on criteria and then groups it before I export it to a database. In the text file I have:
c:\test\123
Other Lines...
c:\test\124
Problem: "description of error". (this error is for directory 124)
Problem: "description of error". (this error is for directory 124)
c:\test\125
...
I would like to group the 'problems' to their associated directory when importing them to the database. So far I have tried using 'foreach' to return the rows where the line contains/begins with directory or problem. Although this passes the value in order it is not clear for users to see which directory the problem belongs to. Ideally I am after:
Directory(column1) Problem(column2)
c:\test\123 || Null
c:\test\124 || Problem: "description of Error".
c:\test\124 || Problem: "description of Error".
c:\test\125 || Null
Any help that you can give would be greatly appreciated. I have been racking my brains on this for the last week!
(current code)
var lines = File.ReadAllLines(filename);
foreach (var line in File.ReadLines(filename))
{
String stringTest = line;
if (stringTest.Contains(directory))
{
String test = stringTest;
var csb = new SqlConnectionStringBuilder();
csb.DataSource = host;
csb.InitialCatalog = catalog;
csb.UserID = user;
csb.Password = pass;
using (var sc = new SqlConnection(csb.ConnectionString))
using (var cmd = sc.CreateCommand())
{
sc.Open();
cmd.CommandText = "DELETE FROM table";
cmd.CommandText = "INSERT INTO table (ID, Directory) values (NEWID(), #val)";
cmd.Parameters.AddWithValue("#VAL", test);
cmd.ExecuteNonQuery();
sc.Close();
}
}
if (stringTest.Contains(problem))
{
Same for problem....
Here is one solution:
Assuming that you have the following class to hold a result item:
public class ResultItem
{
public string Directory { get; set; }
public string Problem { get; set; }
}
You can do the following:
var lines = File.ReadAllLines(filename);
string current_directory = null;
List<ResultItem> results = new List<ResultItem>();
//maintain the number of results added for the current directory
int problems_added_for_current_directory = 0;
foreach (var line in lines)
{
if (line.StartsWith("c:\\test"))
{
//If we are changing to a new directory
//And we didn't add any items for current directory
//Add a null result item
if (current_directory != null && problems_added_for_current_directory == 0)
{
results.Add(new ResultItem
{
Directory = current_directory,
Problem = null
});
}
current_directory = line;
problems_added_for_current_directory = 0;
}
else if (line.StartsWith("Problem"))
{
results.Add(new ResultItem
{
Directory = current_directory,
Problem = line
});
problems_added_for_current_directory++;
}
}
//If we are done looping
//And we didn't add any items for current (last) directory
//Add a null result item
if (current_directory != null && problems_added_for_current_directory == 0)
{
results.Add(new ResultItem
{
Directory = current_directory,
Problem = null
});
}

How to Set default combobox

So I've been looking to set a default value for my combobox. I found a few things but none of them seem to work.
Actually, it works if I create a simple combobox and use comboBox1.SelectedIndex = comboBox1.Items.IndexOf("something") but once I dynamically generate the contents of the comboboxes, I can't get it to work anymore.
This is how I fill my combo box (located in the class's constructor);
string command = "SELECT category_id, name FROM CATEGORY ORDER BY name";
List<string[]> list = database.Select(command, false);
cbxCategory.Items.Clear();
foreach (string[] result in list)
{
cbxCategory.Items.Add(new ComboBoxItem(result[1], result[0]));
}
I can't seem to get it to work to set a default value, like if I place cbxCategory.SelectedIndex = cbxCategory.Items.IndexOf("New") below the above code, it won't work.
WinForms, by the way.
Thank you in advance.
cbxCategory.SelectedIndex should be set to an integer from 0 to Items.Count-1 like
cbxCategory.SelectedIndex = 2;
your
cbxCategory.SelectedIndex = cbxCategory.Items.IndexOf("New")
should return -1 as long as no ComboboxItem mutches the string ("New");
another solution though i don't like it much would be
foreach(object obj in cbxCategory.Items){
String[2] objArray = (String[])obj ;
if(objArray[1] == "New"){
cbxCategory.SelectedItem = obj;
break;
}
}
perhaps this also requires the following transformation to your code
foreach (string[] result in list)
{
cbxCategory.Items.Add(result);
}
I haven't tested the code and i am not sure about the casting to String[2] but something similar should work
It looks like you're searching the cbxCategory.Items collection for a string, but it contains items of type ComboBoxItem. Therefore the search will return -1.
You can use LINQ.
//string command = "SELECT category_id, name FROM CATEGORY ORDER BY name";
//List<string[]> list = database.Select(command, false);
// sample data...
List<string[]> list = new List<string[]> { new string[] { "aaa", "bbb" }, new string[] { "ccc", "ddd" } };
cbxCategory.Items.Clear();
foreach (string[] result in list)
{
cbxCategory.Items.Add(new ComboBoxItem(result[1], result[0]));
}
ComboBoxItem tmp = cbxCategory.Items.OfType<ComboBoxItem>().Where(x => x.ResultFirst == "bbb").FirstOrDefault();
if (tmp != null)
cbxCategory.SelectedIndex = cbxCategory.Items.IndexOf(tmp);
ComboBoxItem class:
class ComboBoxItem
{
public string ResultFirst { get; set; }
public string ResultSecond { get; set; }
public ComboBoxItem(string first, string second)
{
ResultFirst = first;
ResultSecond = second;
}
}
Here's my simple solution
var list = comboBox1.Items.Cast<string>().ToList();
cbxCategory.SelectedIndex = list.FindIndex(c => c.StartsWith("test"));
My solution:
int? defaultID = null;
foreach (DataRow dr in dataSource.Tables["DataTableName"].Rows)
{
if ((dr["Name"] != DBNull.Value) && ((string)dr["Name"] == "Default Name"))
{
defaultID = (int)dr["ID"];
}
}
if (defaultID != null) comboBox.SelectedValue = defaultID;

Categories

Resources