I have 3 dropdown list with the below data format.
Dropdown-1 Dropdown-2 Dropdown-3
----------- -------------- ---------------
Parent-1 Boy-1 Girl-1
Parent-2 Boy-2 Girl-2
Parent-3 Boy-3 Girl-3
Based on the selection from the dropdown boxes;
If I select
Parent-2 from Dropdown-1
Boy-1 from Dropdown-2
Girl-2 from Dropdown-3
Then I need result in the following hierarchical format:
Parent 1
Boy 1
Name 1:
Age 1:
Girl 1
Name 1:
Age 1:
Girl 2
Name 2:
Age 2:
Parent 2
Boy 1
Name 1:
Age 1:
Girl 1
Name 1:
Age 1:
Girl 2
Name 2:
Age 2:
Need your support on this.
Thanks in advance,
kka_anand
I tried with TreeView class and able to create Parent and child object. When I tried to create grantchild. It throws error in the below marked area. Any suggestion to fix it.
//=============================================================
// Add a child treenode for each NameAge object in the current Gender object.
foreach (NameAge noOfNameAge in noOfParents.ParentOrder)
{
controllerOutput.Nodes[parentArray.IndexOf(noOfParents)].Nodes[genderArray.IndexOf(noOfGender)].Nodes.Add(
new TreeNode(noOfNameAge.NameAgeID));
}
//=============================================================
// Start of parent class.
public class Parent : System.Object
{
private string parentName = "";
protected ArrayList parentOrder = new ArrayList();
public Floor(string parentName)
{
this.floorName = parentName;
}
public string ParentName
{
get { return this.parentName; }
set { this.parentName = value; }
}
public ArrayList ParentOrder
{
get { return this.parentOrder; }
}
} // End of parent class.
// Start of gender (Boy/Girl) class.
public class Corridor : System.Object
{
private string genderID = "";
protected ArrayList genderOrder = new ArrayList();
public Gender(string genderid)
{
this.genderID = genderid;
}
public string GenderID
{
get { return this.genderID; }
set { this.genderID = value; }
}
public ArrayList GenderOrder
{
get { return this.genderOrder; }
}
} // End of gender class.
// Start of NameAge class.
public class NameAge : System.Object
{
private string nameageID = "";
protected ArrayList nameageOrder = new ArrayList();
public NameAge(string nameageid)
{
this.nameageID = nameageid;
}
public string NameAgeID
{
get { return this.NameAgeID; }
set { this.NameAgeID = value; }
}
public ArrayList NameAgeOrder
{
get { return this.nameageOrder; }
}
} // End of NameAge class.
private ArrayList parentArray = new ArrayList();
private ArrayList genderArray = new ArrayList();
private ArrayList nameageArray = new ArrayList();
private void FillControllerTreeView()
{
// Add parent to the ArrayList of Parent objects.
for (int x = 1; x <= Convert.ToInt32(DropDown-1.SelectedItem.ToString()); x++)
{
parentArray.Add(new Parent("Parent - " + x.ToString()));
}
// Add Gender(Boy/Girl) to each Parent object in the ArrayList.
foreach (Parent parent in parentArray)
{
for (int y = 1; y <= Convert.ToInt32(DropDown-2.SelectedItem.ToString()); y++)
{
parent.ParentOrder.Add(new Gender("Boy - " + y.ToString()));
}
for (int z = 1; z <= Convert.ToInt32(DropDown-3.SelectedItem.ToString()); z++)
{
parent.ParentOrder.Add(new Gender("Girl - " + z.ToString()));
}
}
foreach (NameAge nameage in nameageArray)
{
for (int y = 0; y <= 2; y++)
{
nameage.NameAgeOrder.Add(new NameAge("Light - " + y.ToString()));
}
nameage.NameAgeOrder.Add(new NameAge("AC - "));
}
controllerOutput.BeginUpdate();
controllerOutput.Nodes.Clear();
foreach (Parent noOfParents in parentArray)
{
controllerOutput.Nodes.Add(new TreeNode(noOfParents.ParentName));
// Add a child treenode for each gender object in the current Parent object.
foreach (Gender noOfGender in noOfParents.ParentOrder)
{
controllerOutput.Nodes[parentArray.IndexOf(noOfParents)].Nodes.Add(
new TreeNode(noOfGender.GenderID));
// Add a child treenode for each NameAge object in the current Gender object.
foreach (NameAge noOfNameAge in noOfParents.ParentOrder)
{
controllerOutput.Nodes[parentArray.IndexOf(noOfParents)].Nodes[genderArray.IndexOf(noOfGender)].Nodes.Add(
new TreeNode(noOfNameAge.NameAgeID));
}
}
}
controllerOutput.EndUpdate();
}
Thanks
Related
suppose this base class
public class Contrat_Paye_Item
{
public int CPI_TYPE { get; set; }
public string CPI_TEXT { get; set; }
public decimal CPI_AMOUNT { get; set; }
}
in my view Model i have made a list from that class like this :
private ObservableCollection<Contrat_Paye_Item> listapayer;
public ObservableCollection<Contrat_Paye_Item> ListaPayer
{
get
{
return listapayer;
}
set
{
listapayer = value;
OnPropertyChanged("ListaPayer");
}
}
and in the VM constructor, just some testdata :
listapayer.Add(new Contrat_Paye_Item()
{
CPI_TYPE = 0,
CPI_TEXT = "Loyer",
CPI_AMOUNT = 100
});
listapayer.Add(new Contrat_Paye_Item()
{
CPI_TYPE = 1,
CPI_TEXT = "charge 1",
CPI_AMOUNT = 200
});
listapayer.Add(new Contrat_Paye_Item()
{
CPI_TYPE = 1,
CPI_TEXT = "Charges 2",
CPI_AMOUNT = 300
});
so the full list contain 3 item, the total Amount is 600 .
in my viewmodel i have added a sublist with only items that their CPI_TYPE = 1 and bound it to a listbox without problem like this :
public ICollectionView ListCharges
{
get
{
var sub= new CollectionViewSource { Source = listapayer }.View;
sub.Filter = p => (p as Contrat_Paye_Item).CPI_TYPE == 1;
return sub;
}
}
now what i want to display is a list of my items , with a row that contain a sum of amounts items of the sublist . a bind it to a second listbox
something like :
loyer 100
charges 500
any idea, tip is welcome .
thanks
How about adding something like this before returning the sub:
var d1 = (from a in sub.SourceCollection.OfType<Contrat_Paye_Item>() where a.CPI_TEXT == "Loyer" select a.CPI_AMOUNT).Sum();
var d2 = (from a in sub.SourceCollection.OfType<Contrat_Paye_Item>() where a.CPI_TEXT.ToLower().StartsWith("charge") select a.CPI_AMOUNT).Sum();
sub.AddNewItem(new Contrat_Paye_Item() { CPI_TEXT="Sum Loyer", CPI_AMOUNT = d1} );
sub.CommitNew();
sub.AddNewItem(new Contrat_Paye_Item() { CPI_TEXT = "Sum Charges", CPI_AMOUNT = d2 });
sub.CommitNew();
//Edit
Note this as a more flexible possibility:
Do not use _CollectionViewSource _. Instead use the following as the ItemsSource of the ListBox:
public ObservableCollection<Contrat_Paye_Item> ListCharges
{
get
{
return new ObservableCollection<Contrat_Paye_Item>((from a in listapayer where a.CPI_TYPE == 1 select a));
}
}
I created a parser that reads files formatted in the following way:
version="v4.5.32"
name="Test File"
date="2513.04.02"
players=
{
{
first_name="John"
last_name="Smith"
country=12
id=0
}
{
first_name="Mario"
last_name="Rossi"
country=56
id=1
}
}
next_player_id=2
matches=
{
22 47 88 1045 1048 3511
}
settings=
{
match_prefix="game"
match_reward_scalar=1,55
match_sets_points=
{
0,5 0,75 1,0
}
next_event_id=56
next_event_fired=false
next_event_probability=0,33
}
...
Basically, those files contain a list of key/value pairs in which keys are always a string and values can be either a simple value (boolean, date, float, integer, string), a record (a sublist of key/value pairs like settings) or an array (composed by simple values like matches or records like players). In order to parse and handle those values I created 3 simple classes.
1) MyPair
public sealed class MyPair
{
public MyKey Key { get; }
public MyValue Value { get; }
public MyPair(MyKey key, MyValue value) { ... }
public override String ToString()
{
return String.Concat(Key, " = ", Value);
}
}
2) MyKey
public sealed class MyKey
{
public String Name { get; }
... // other properties set by checking the name in the constructor
public Key(String name) { ... }
public override String ToString()
{
return Name;
}
}
3) MyValue
public sealed class MyValue
{
private readonly dynamic m_UnderlyingValue;
private readonly MyValueCategory m_Category;
public dynamic UnderlyingValue
{
get { return m_UnderlyingValue; }
}
public Boolean Container
{
get { return ((m_Category == ValueCategory.Array) || (m_Category == ValueCategory.Record)); }
}
public MyValueCategory Category
{
get { return m_Category; }
}
public MyValue(DateTime underlyingValue)
{
if (underlyingValue == null)
throw new ArgumentNullException("underlyingValue");
m_UnderlyingValue = underlyingValue;
m_Category = MyValueCategory.DateTime;
}
public MyValue(Boolean underlyingValue) { ... }
public MyValue(Double underlyingValue) { ... }
public MyValue(Int64 underlyingValue) { ... }
public MyValue(MyPair[] underlyingValue) { ... }
public MyValue(MyValue[] underlyingValue) { ... }
public MyValue(String underlyingValue) { ... }
public override String ToString()
{
switch (m_Category)
{
case MyValueCategory.Array:
return String.Concat("Array[", m_UnderlyingValue.Length, "]");
case MyValueCategory.Boolean:
return String.Concat("Boolean[", (m_UnderlyingValue ? "true" : "false"), "]");
case MyValueCategory.DateTime:
return String.Concat("DateTime[", m_UnderlyingValue.ToString("yyyy.MM.dd", CultureInfo.InvariantCulture), "]");
case MyValueCategory.Float:
return String.Concat("Float[", m_UnderlyingValue.ToString("F3", CultureInfo.InvariantCulture), "]");
case MyValueCategory.Integer:
return String.Concat("Integer[", m_UnderlyingValue.ToString("F0", CultureInfo.InvariantCulture), "]");
case MyValueCategory.Record:
return String.Concat("Record[", m_UnderlyingValue.Length, "]");
default:
return String.Concat("Text[", m_UnderlyingValue, "]");
}
}
}
public enum MyValueCategory
{
Array,
Boolean,
DateTime,
Float,
Integer,
Record,
Text
}
The parsing process works like a charm and returns me a MyValue instance that works like a container / root node for everything I parsed.
I'm not using WPF forms, just plain Winforms. I would like to populate a TreeView control hierarchically with the parsed data and then make that data responsive to the changes made to the TreeView nodes. I really can't figure out how to bind data to the control itself and allow a mirrored manipulation.
Any suggestion please?
You can populate your TreeView recursively with this code:
protected override void OnLoad( EventArgs e )
{
base.OnLoad( e );
MyValue root = new MyParser().Parse( "MyFilename.own" );
Populate( treeView1.Nodes, root.UnderlyingValue );
}
protected void Populate( TreeNodeCollection nodes, IList list )
{
if( list is MyPair[] )
{
foreach( MyPair pair in list )
{
TreeNode node = new TreeNode();
node.Text = pair.ToString();
node.Tag = pair;
nodes.Add( node );
if( pair.Value.Container )
Populate( node.Nodes, (IList)pair.Value.UnderlyingValue );
}
}
if( list is MyValue[] )
{
foreach( MyValue value in list )
{
TreeNode node = new TreeNode();
node.Text = value.ToString();
node.Tag = value;
nodes.Add( node );
if( value.Container )
Populate( node.Nodes, (IList)value.UnderlyingValue );
}
}
}
Result looks then like that:
As #Reza Aghaei already mentioned it is not possible to do this via data-binding. You have to maintain your lists manually after adding/removing a node. Setting node.Tag to the corresponding pair or value makes it easy for you to find and modify them.
whenever a change is occured changes i call this set_filelist_inventory(). and send a new list to this function but UI is not upadating.
public partial class Inventory : UserControl
{
public List<String> file_list = new List<String>();
public void set_filelist_inventory(List<string> x)
{
if (file_list.SequenceEqual(x)) { }
else
{
file_list = x;
Dispatcher.Invoke(() =>
{
listview1.ItemsSource = file_list;
});
}
}
public Inventory()
{
InitializeComponent();
file_list = General.GetFileList();
Discover d = new Discover();
d.send(d);
listview1.ItemsSource = file_list;
}
}
I tried removing if else block. it still didn't worked.
I am not having any issues making calls from the form instance to the Revit class. It's when I try to assign a List to the Revit class's function categoryList(), that I get a variable doesn't exist in the context error. I tried prefixing a reference to the instance of the form class "Form UF = new Form;" This doesn't work.
//The Revit Class
public Result Execute(ExternalCommandData commandData, ref string message,....)
{
User_Form UF = new User_Form(commandData);
UF.ShowDialog();
public List<BuiltInCategory> categoryList(Document doc, int intSwitch)
{
//list built in categories for built in filter_1
builtInCats_List = new List<BuiltInCategory>();
switch (intSwitch)
{
case (1):
...
case (3):
...
case (4):
{
builtInCats_List = newStateCb1;
return builtInCats_List;
}
default:
{
builtInCats_List = newStateCb1;
return builtInCats_List;
}
}
}
using Form = System.Windows.Forms.Form;
using WS = ModelAuditor_2014.WorksetSorter_2014;
using ModelAuditor_2014;
using System.Threading;
//The Form
namespace ModelAuditor_2014
{
public partial class User_Form : Form
{
//Constructor
WorksetSorter_2014 WS = new WorksetSorter_2014();
//Revit references
public Autodesk.Revit.UI.UIApplication rvtUiApp;
public Autodesk.Revit.UI.UIDocument rvtUiDoc;
public Autodesk.Revit.ApplicationServices.Application rvtApp;
//Global Variables
public List<BuiltInCategory> Filter01_CategoryList;
public List<BuiltInCategory> Filter02_CategoryList;
public int intSwitch;
public List<BuiltInCategory> newStateCb1;
public User_Form(ExternalCommandData commandData)
{
//Revit references
rvtUiApp = commandData.Application;
rvtUiDoc = rvtUiApp.ActiveUIDocument;
rvtApp = rvtUiApp.Application;
InitializeComponent();
}
public void User_Form_Load(object sender, EventArgs e)
{
//use rvtDoc = Doc
Autodesk.Revit.DB.Document rvtDoc = .....
//CheckedListBox for filter01
checkedListBox1.DataSource = WS.categoryList(rvtDoc, intSwitch = 1);
Filter01_CategoryList = new List<BuiltInCategory>();
Filter01_CategoryList = WS.RetrieveSchema(rvtDoc, false);
foreach (BuiltInCategory ChkedB1 in Filter01_CategoryList)
{
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
if (checkedListBox1.Items[i].ToString() == ChkedB1.ToString())
{
checkedListBox1.SetItemChecked(i, true);
}
}
}
public List<BuiltInCategory> returnNewStateCB1()
{
newStateCb1 = checkedListBox1.CheckedItems.Cast
<BuiltInCategory>().ToList<BuiltInCategory>();
return newStateCb1;
}
I passed the list from the win form to another public function in the revit app, I was able to access the list returned by this function.
I am trying to get my hands on WPF, and I have encountered a small problem when updating, mainly that I am getting the old data displayed while the new data is correctly updated in the XML file. I have implemented INotifyPropertyChanged as follows :-
public class Products : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _prodId;
public string ProdID
{
get { return _prodId; }
set
{
_prodId = value;
OnPropertyChanged("ProdID");
}
}
private string _prodName;
public string ProdName
{
get { return _prodName; }
set
{
_prodName = value;
OnPropertyChanged("ProdName");
}
}
private string _prodPrice;
public string ProdPrice
{
get { return _prodPrice; }
set
{
_prodPrice = value;
OnPropertyChanged("ProdPrice");
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
and then the update is as follows :-
foreach (XmlNode node in nodeList)
{
if (nodeList[i].ChildNodes[0].InnerText == strID)
{
Products products = new Products();
products.ProdName = strName;
products.ProdPrice = strPrice;
nodeList[i].ChildNodes[1].InnerText = strName;
nodeList[i].ChildNodes[2].InnerText = strPrice;
break;
}
i++;
}
The XML is being saved correctly with the new ProdName and Price, however when I display the listView after the update, i am still getting the wrong values.
I am binding the Products like this:-
public static List<Products> LoadProduct()
{
string fileName = "Products.xml";
List<Products> ListProdRecords = new List<Products>();
// Execute the query using the LINQ to XML
var prods = from p in XElement.Load(fileName).Elements("Product") select p;
foreach (var product in prods)
{
Products lProduct = new Products
{
ProdID = product.Element("ProductId").Value,
ProdName = product.Element("ProductName").Value,
ProdPrice = product.Element("Price").Value
};
ListProdRecords.Add(lProduct);
}
return ListProdRecords.ToList();
}
here is the binding code :-
private void LoadProducts()
{
List<Products> productList = new List<Products>();
productList = ProductDAL.LoadProduct();
listView1.DataContext = productList;
}
public static void UpdateProduct(string strID, string strName, string strPrice)
{
string fileName = "Products.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(fileName);
XmlNodeList nodeList = xmlDoc.SelectNodes("/Products/Product");
int i = 0;
foreach (XmlNode node in nodeList)
{
if (nodeList[i].ChildNodes[0].InnerText == strID)
{
Products products = new Products();
products.ProdName = strName;
products.ProdPrice = strPrice;
nodeList[i].ChildNodes[1].InnerText = strName;
nodeList[i].ChildNodes[2].InnerText = strPrice;
break;
}
i++;
}
Any help on what's wrong?
Thanks for your help and time
I don't really see, what the newly created products in your loop have to do with a listView. You don't add them to a list or add them to the listView in another way.
Or in other words: The creation of those instances inside your loop is completely useless and will be removed by the optimizer.
You need to update the instances of the Products class that are in the list you bound to the listView.