I want to implement a Hierarchical data bound control for ASP.NET.
I used Implementing IHierarchy Support Into Your Custom Collection as a basis to create my hierarchical collection. I also created a HierarchicalDataSourceControl for the collection. Everything works: I can bind it to an ASP.NET TreeView and it renders the data correctly.
However, I'm stuck on the HierarchicalDataBoundControl. I found examples, but I am still too new at c# / .Net to understand them. I don't quite understand how to implement the examples:
Rendering a databound UL menu
nor
HierarchicalDataBoundControl Class
Does anyone have any tips, or better examples of implementing a control like this?
As another DataBound controls you have to override PerformDataBinding method as follows.
protected override void PerformDataBinding()
{
base.PerformDataBinding();
if (!IsBoundUsingDataSourceID && this.DataSource == null) return;
HierarchicalDataSourceView view = this.GetData(string.Empty);
if (view != null)
{
IHierarchicalEnumerable root = view.Select();
}
}
Whereas your control supports DataSource and HierarchialDataSource control in this case, should check if there is an assigned DataSource, get its DataSourceView to accomplish data binding. It's practicable through GetData method. Then call view's Select method to get the root collection.
Afterwards, you have to iterate through root collection that is an object of type IHierarchialEnumerable. It has a simple method called GetHierarchyData that gives an object which is an item of the collection and returns an associated IHierarchyData that describes a node. This methods is there, therefore in most times you don't know the actual type of item. IHierarchyData represents some information about a node and its children.
Lastly, you don't need to write a new DataSource control. If you are after creating a custom navigation control, it's better to write a new provider for SiteMapDataSource.
I faced similar problem and created my own raw html.
private void LoadCategory()
{
String s = "";
// Prepare your dataset DataSet ds
// Note That I have Category Table having C_NAME AND PC_NAME coloums, change it as per your column anme
ds.Relations.Add("rsParentChild", ds.Tables[0].Columns["C_NAME"], ds.Tables[0].Columns["PC_NAME"]);
s = s + "\n <table>";
s = s + "\n <tr>";
s = s + "\n <td class='br4'> ";
s = s + "\n <table>";
s = s + "\n <tr>";
s = s + "\n <td>";
s = s + "\n <ul id='qm0' class='qmmc'>";
foreach (DataRow dr in ds.Tables[0].Rows)
{
if (dr["PC_NAME"] == DBNull.Value)
{
s = s + "\n <li><a class='qmparent' href='#'>" + dr["C_NAME"].ToString() + "</a>";
s = s + "\n <ul>" + PopulateTree(dr) + "</ul>";
}
}
s = s + "\n <li class='qmclear'> </li></ul>";
s = s + "\n <script type='text/javascript'>qm_create(0,true,0,500,'all',false,false,false,false);</script>";
s = s + "\n </td>";
s = s + "\n </tr>";
s = s + "\n </table>";
s = s + "\n </td>";
s = s + "\n </tr>";
s = s + "\n </table>";
Literal1.Text = s;
}
private String PopulateTree(DataRow dr)
{
String s = "";
String ss;
foreach (DataRow row in dr.GetChildRows("rsParentChild"))
{
s = s + " <li>" + row["C_NAME"].ToString() + "\n";
ss = PopulateTree(row);
if (ss != "")
s = s + " <ul>" + ss + "</ul></li>\n\n";
}
return s;
}
Related
I need to identify all drives and all logical partitions of each drive and I am having really troubles while dealing with memory cards (integrated reader in the laptop).
I am using this code
void GetFullInfoDiskDrives()
{
Global.LogMessage("************** GetFullInfoDiskDrives() Getting complete info from all disk drives ", 1);
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject info in searcher.Get())
{
// Lets print all the properties per disk
PropertyDataCollection properties = info.Properties;
// display the properties
Global.LogMessage("----------------- Properties for the disk " + info["Model"].ToString(),1);
foreach (PropertyData property in properties)
{
Global.LogMessage("[" + property.Name + "] = '" + property.Value +"'", 1);
foreach (QualifierData q in property.Qualifiers)
{
Global.LogMessage(" -" + q.Name + "- = '" + q.Value + "'", 1);
}
}
string s = "";
string s_model = info["Model"].ToString();
string s_interface = (info["InterfaceType"]==null? info["MediaType"].ToString():info["InterfaceType"].ToString());
string s_serialnumber = (info["SerialNumber"] == null ? "No serial number": info["SerialNumber"].ToString());
Global.LogMessage("Disk detected (Model: " + s_model + " | Interface: " + s_interface + " | Serial#: " + s_serialnumber,1);
foreach (ManagementObject o in info.GetRelated("Win32_DiskPartition"))
foreach (ManagementObject i in o.GetRelated("Win32_LogicalDisk"))
s += i["Name"] + " ";
Global.LogMessage("Logical disks: " + s,1);
}
}
The memory card doesn't seem to have a value for InterfaceType so I need to read MediaType instead. The same happens with the serial number, I don't know where to find it for a memory card.
Also, many values show its type (of value) in the value property such as
[Capabilities] = 'System.UInt16[]'
-CIMTYPE- = 'uint16'
How can I get the real value of this property?
I admit I am a bit lost and diving in the official documentation is not an easy task... :/
Could anybody put some light ?
Thanks!
Jose
After the good above suggestion from Rene, I tried to make it as dynamically as possible.
my goal is to cast the Property.value using the type from the value from the related QualifierData object.
My final working code is here. I am sure that there are more elegant ways to achieve it but this is the one I found. ;)
foreach (PropertyData property in properties){
foreach (QualifierData q in property.Qualifiers){
if (property.IsArray){
if (property.Value != null){
Type t = property.Value.GetType();
object o = property.Value;
dynamic foo = o;
if (IsPropertyExist(foo, "Length")){
string s1 = "";
for (int i = 0; i < foo.Length; i++)
s1 += "[" +foo[i] +"]";
Global.LogMessage("[" + property.Name + "] (" + q.Value + ") = " + s1 , 1);
}
I'm trying to search for a certain number(object) in a listbox which comes together with a string in order to highlight it. In the following bit of code i override a ToString() method to contain all my objects.
public override string ToString()
{
string reservatiestring;
reservatiestring = "Kamer: " + roomNumber + "" + " Op datum: " + datum + " Aantal personen: " + personen.Count + " Naam: " + reservatienaam;
return reservatiestring;
}
Following this I add it to my listbox in the following bit of code:
listBox1.Items.Add(reservatie.ToString());
I now want to search for all the items in my listbox containing the same roomNumber object. To do this i tried the Contains() method with the text before it: "Kamer: " and the object which I'm looking for +comboBox1.SelectedItem. This however always fails and my code goes to the else option giving me the error message.
private void buttonSearch_Click(object sender, EventArgs e)
{
listBox1.SelectionMode = SelectionMode.MultiExtended;
Reservations reservaties = new Reservations();
reservaties.roomnumberstring = "Kamer: " + comboBox1.SelectedValue;
for (int i = listBox1.Items.Count - 1; i >= 0; i--)
{
if (listBox1.Items[i].ToString().ToLower().Contains(("Kamer: " + comboBox1.SelectedValue)))
{
listBox1.SetSelected(i, true);
}
else
{
MessageBox.Show("error");
}
Please note: All my roomNumber objects are stored in the combobox, so whenever i select for example roomNumber 3 in my combobox and hit search all the items in the listbox containing "Kamer: 3" should be selected.
The roomnumberstring is a option I tried which did not work unfortunately.
reservaties.roomnumberstring = "Kamer: " + comboBox1.SelectedValue;
Your override of the ToString method is wrong and won't modify anything. Try this :
public override string ToString(this string reservatiestring)
{
reservatiestring = "Kamer: " + roomNumber + "" + " Op datum: " + datum + " Aantal personen: " + personen.Count + " Naam: " + reservatienaam;
return reservatiestring;
}
I can see one thing that might make your code fail. you are comparing
.ToLower()
with "Kamer", where the "K" isnĀ“t in lowercase
I want to set the values of my selected item in my combo box to a variable(person) so that I can compare a person value to a value in my sqlite database. Here is my code:
private void cboSelectClient_SelectedIndexChanged(object sender, EventArgs e)
{
string str;
personSearch = new Person();
selectedPersonList = new List<Person>();
My problem is in the next line, where it should set my person variable items equal too the items that is in the combobox.
personSearch = cboSelectClient.SelectedItem as Person;
_pBl.PopulateSelectedPersonList(personSearch, ref selectedPersonList);
foreach (Person person in selectedPersonList)
{
txtAge.Text = Convert.ToString(person.Age);
txtEmail.Text = person.Email;
txtFirstName.Text = person.FirstName;
txtID.Text = Convert.ToString(person.ID);
txtLastName.Text = person.LastName;
lstItemsAdded.Items.Add(person.Item);
}
}
This is how i populate my combobox:
foreach (Person PersonItem in _listAllData)
{
if (PersonItem.FirstName != equalPerson.FirstName) //Add name en add nie die name wat klaar in is nie... VIND UIT HOE OM NET N SEKERE DEEL TE ADD..
{
cboSelectClient.Items.Add(PersonItem.ID +" : "
+ PersonItem.FirstName + " "
+ PersonItem.LastName + " "
+ PersonItem.Age + " "
+ PersonItem.Email + " "
+ PersonItem.Item.ItemCode
+ " " + PersonItem.Item.ItemDescription
+ " " + PersonItem.Item.ItemName + " "
+ PersonItem.Item.ItemPrice);
}
equalPerson = PersonItem;
}
Problem here is that you are populating your ComboBox with string, not with actual Person object. Of course this string cannot be converted directly back to object, therefore your conversion fails and personSearch is assigned to null.
To resolve the issue you need to:
Populate ComboBox with actual Person objects. Make sure ComboBox.ValueMemeber is null.
In Person class define some property like Text and set DisplayMember to it or override ToString to control how entries in CombobBox appear on the UI
I would like to click on an item in a listbox and display the attributes that were passed into that listbox to a multiline textbox.
Below is the code I have written on form initialisation
public Form1()
{
InitializeComponent();
ReadFromFile.Read("sample.GED");
foreach (KeyValuePair<int, Individual> kvp in ReadFromFile.individuals)
{
listBox2.Items.Add("ID = " + kvp.Value.id + " Name = " + kvp.Value.name.givenName + " " + kvp.Value.name.surname + " DoB = " + kvp.Value.birth.date);
}
int testIndividual = 94;
string genderOut = "";
if (ReadFromFile.individuals[testIndividual].gender == "M")
{
genderOut = "MALE";
}
else if (ReadFromFile.individuals[testIndividual].gender == "F")
{
genderOut = "FEMALE";
}
try
{
textBox1.AppendText(
"Name = " + ReadFromFile.individuals[testIndividual].name.givenName + " "
+ ReadFromFile.individuals[testIndividual].name.surname
+ Environment.NewLine + "Gender = " + genderOut
+ Environment.NewLine + "Birth date = " + ReadFromFile.individuals[testIndividual].birth.date
+ Environment.NewLine + "Birth place = " + ReadFromFile.individuals[testIndividual].birth.place
+ Environment.NewLine + "Death date = " + ReadFromFile.individuals[testIndividual].death.date
+ Environment.NewLine + "Death place = " + ReadFromFile.individuals[testIndividual].death.place);
}
catch
{
MessageBox.Show("This individual doesnt exist");
}
}
}
I would like to add more so I can click on a listbox item and the details for that item will be shown in the textbox
I get the feeling I may have to override the ToString() method or regex it. Im still quite a novice programmer so go easy on me :) THANK YOU
You need to handle the SelectedIndexChanged event for your listbox.
One way to do this is to bring up Form1.cs[Design] and select the listbox. In the property grid (Alt+Enter) click the icon that looks like this:
Find the event SelectedIndexChanged and double click it. That will hook up an event handler for you in the auto generated Form1.cs.designer file.
Next, replace the code for your Form1 class with the following:
public partial class Form1 : Form
{
private Dictionary<int, Individual> _individuals;
public Form1()
{
InitializeComponent();
ReadFromFile.Read("sample.GED");
_individuals = ReadFromFile.individuals;
listBox1.DataSource = _individuals.Select(individual => individual.Value).ToList();
listBox1.DisplayMember = "name";
listBox1.ValueMember = "id";
}
private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
{
textBox1.Clear();
var individual = listBox1.SelectedItem as Individual;
string genderOut = (individual.Gender == "M") ? "MALE" : "FEMALE";
var displayText
= String.Format("Name = {0} {1}\r\n" +
"Gender = {2}\r\n" +
"Birth date = {3}\r\n" +
"Birth place = {4}\r\n" +
"Death date = {5}\r\n" +
"Death place = {6}"
, individual.name.givenName
, individual.name.surname
, genderOut
, individual.birth.date
, individual.birth.place
, individual.death.date
, individual.death.place);
textBox1.AppendText(displayText);
}
}
A few notes about some of the things i've changed.
I've moved the code that was setting the textbox value into the SelectedIndexChanged event handler
I've refactored that code so that it's more readable by using the static String.Format method (all those Environment.NewLine repeats you had were messy).
I've setup the data for the list box using the DataSource property instead of your foreach loop.
Also, one thing you'll notice with this is that the list items in the listbox will not show the correct text. This is because you appear to be using some custom classes or structs for the name, birth and death of an Individual? To fix this, you need to add a new property to the Individual class like this:
public class Individual
{
// ... your code
public string DisplayName
{
get { return String.Format("{0} {1}), name.givenName, name.surname; }
}
// ... the rest of your code
}
Then you will need to change the line in my code above that looks like this:
listBox1.DisplayMember = "name";
to this:
listBox1.DisplayMember = "DisplayName";
Final note: You should probably be using "Upper Camel Case" for your property names. That means that they start with an upper case letter and then the first letter of each word is also upper case. For example, name.givenName should be Name.GivenName. This is a widely used convention.
I added some custom attributes to checkboxlist, but I wonder why I failed to retrieve the values of custom attributes. It will be something like this post jQuery - find control using custom attribute. But what I want is retrieve through auto postback and code behind.
int temp = 0;
foreach (DataRow rows1 in ds_ss_equipments_data.Tables[0].Rows)
{
cblEquip.Items.Add(new ListItem(rows1["name"].ToString() + " " + rows1["quota"].ToString() + " X " + rows1["price"].ToString(), rows1["id"].ToString()));
cblEquip.Items[temp].Attributes["price"] = rows1["price"].ToString();
cblEquip.Items[temp].Attributes["id"] = rows1["id"].ToString();
cblEquip.Items[temp].Attributes["quota"] = rows1["quota"].ToString();
temp += 1;
}
foreach (ListItem li in cblEquip.Items)
{
if (li.Selected)
{
equip += (Convert.ToDecimal(li.Attributes["price"]) * Convert.ToInt32(li.Attributes["quota"]));
}
}
The link provided by Tim will probably solve your problem. Just a note on your programming style. This temp variable looks very strange. Try this
foreach (DataRow rows1 in ds_ss_equipments_data.Tables[0].Rows)
{
var listItem = new ListItem(rows1["name"].ToString() + " " + ...)
listItem.Attributes["price"] = rows1["price"].ToString();
listItem.Attributes["id"] = rows1["id"].ToString();
listItem.Attributes["quota"] = rows1["quota"].ToString();
cblEquip.Items.Add(listItem);
}
It is easier an more comprehensible.
And replace this
rows1["name"].ToString() + " " + rows1["quota"].ToString() + " X " + rows1["price"].ToString()
By this
String.Format("{0} {1} X {2}", rows1["name"], rows1["quota"], rows1["price"])
Creating an item will look much prettier like this
string caption = String.Format(
"{0} {1} X {2}",
rows1["name"],
rows1["quota"],
rows1["price"]
);
var listItem = new ListItem(caption, rows1["id"].ToString())