Assign value to a list of another class - c#

I don't know how to add parameters to a list from a subclass. I have this class:
public partial class remSolicitudesEnt
{
private Solicitud[] solicitudesField;
public Solicitud[] Solicitudes {
get {
return this.solicitudesField;
}
set {
this.solicitudesField = value;
}
}
}
And in my code I have this:
private static remSolicitudesEnt getRemSolicitudesEnt()
{
remSolicitudesEnt filter= new remSolicitudesEnt();
//WHEN I ADD AN ELEMENT TO A NORMAL LIST...
List<Profesional> profesionals = new List<Profesional>();
Profesional p1 = new Profesional();
profesionals.Add(pd1);
//BUT HOW CAN I ADD AN ELEMENT TO A LIST FROM THE SUBCLASS??
Solicitud s = new Solicitud();
//filter.Solicitudes.Add(s); THIS CAN'T BE DONE
}
How Can I add the element "Solicitud" to the list?
Thanks in advance!

Your class is array not a list. So you have not method Add there. Just change definition of your
class:
public partial class remSolicitudesEnt {
private List<Solicitud> solicitudesField;
public List<Solicitud> Solicitudes
{
get { return this.solicitudesField; }
set { this.solicitudesField = value; }
}
}

Related

How can I iterate through a list with multiple objects from class

I am coding an application for my study, but i'm stuck at this point. I made a class called 'Neighborhood'. This class has a string and an int. In my main code I give the class a value and put it in a list. I now want to loop through my list and get the int out of it (put it in a listbox, or do a calculation). How do I get the int out of the list?
class Wijk
{
private string wijken;
private int tijd;
public string Wijken
{
get { return wijken; }
set { wijken = value; }
}
public int Tijd
{
get { return tijd; }
set { tijd = value; }
}
}
Created the list and the instance of the class.
List<object> Uden = new List<object>();
Wijk Wijkeninput = new Wijk();
Now I value the string and int with a combobox and textbox.
private void wijkAanmaken()
{
Wijkeninput.Wijken = Convert.ToString(cbWijken);
Wijkeninput.Tijd = Convert.ToInt16(tbSnelheid.Text);
Uden.Add(Wijkeninput);
}
For this, instead of having an object list, you can have list containing class objects like
List<Wjik> Uden = new List<Wjik>();
then you can access int as follows:
foreach (Wjik obj in listProgram)
{
int tij = Convert.ToInt32(obj.tijd);
}
First the List can be declared like this:
List<Wijk> Uden = new List<Wijk>();
To iterate over it:
foreach(var item in Uden)
{
var myInt = item.Tijd;
var myString = item.Wijken;
//here do whatever you want with the values
}

Xml List Serialization and Node Type Names

Ive come across multiple questions and answers on here but none specific to my situation.
I have a class 'Entity' with multiple classes that extend off of it. I want the serialization to hit the list and understand and use the type of each item for the node name.
Now, I can use what is commented out (define each array item in the main class and define the name of such by using [XmlArrayItem("Subclass1", typeof(subclass1)] but I want to keep all definitions in their subclass and I will be having too many subclasses to define everything in the main entity class...Is there anyway to achieve this?
I have tried using [XmlType(TypeName="...")] for the subclasses and so on but that did not work.
[Serializable]
[XmlInclude(typeof(Subclass1))]
[XmlRoot("Entity")]
public class Entity{
[XmlArray("CausedBy")]
//[XmlArrayItem("Subclass1", typeof(subclass1))]
//[XmlArrayItem("Sublcass2", typeof(Subclass2))]
public List<Entity> CausedBy { get; set; }
}
[Serializable]
[XmlRoot("Subclass1")]
[XmlInclude(typeof(Subclass2))]
public class Subclass1:Entity{
//Code...
}
[Serializable]
[XmlRoot("Subclass2")]
public class Subclass2:Subclass1{
//Code...
}
Serializing the above code after creating an entity and adding a Subclass1 and Subclass2 to the list 'CausedBy' class results in the following:
<Entity>
<CausedBy>
<Entity ... xsi:type="SubClass1" />
<Entity ... xsi:type="SubClass2" />
</CausedBy>
<Entity>
I would like the output to show:
<Entity>
<CausedBy>
<SubClass1 .../>
<SubClass2 .../>
</CausedBy>
<Entity>
Since I totally failed to read the question to begin with, here's a new answer (it's a bit of a tl;dr, so you can always skip to the end and follow the link):
It isn't possible to get the built in serializer class to work because you don't wish to add the attributes that it needs to be able to operate. Your only option is to seralize the class yourself, however, this need not be as tedious as it sounds; I had a similar issue a few years ago with DataGridView in virtual mode and produced a generic virtualizer that could be used to virtualize the data for display; it used a custom attribute:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class showColumnAttribute : System.Attribute
{
///<summary>Optional display format for column</summary>
public string Format;
///<summary>Optional Header string for column<para>Defaults to propety name</para></summary>
public string Title;
///<summary>Optional column edit flag - defaults to false</summary>
public bool ReadOnly;
///<summary>Optional column width</summary>
public int Width;
///<summary>
///Marks public properties that are to be displayed in columns
///</summary>
public showColumnAttribute()
{
Format = String.Empty;
Title = String.Empty;
ReadOnly = false;
Width = 0;
}
}
And a constructor:
///<summary>
///Extracts the properties of the supplied type that are to be displayed
///<para>The type must be a class or an InvalidOperationException will be thrown</para>
///</summary>
public Virtualiser(Type t)
{
if (!t.IsClass)
throw new InvalidOperationException("Supplied type is not a class");
List<VirtualColumnInfo> definedColumns = new List<VirtualColumnInfo>();
PropertyInfo[] ps = t.GetProperties();
MethodInfo mg, ms;
for (int i = 0; i < ps.Length; i++)
{
Object[] attr = ps[i].GetCustomAttributes(true);
if (attr.Length > 0)
{
foreach (var a in attr)
{
showColumnAttribute ca = a as showColumnAttribute;
if (ca != null)
{
mg = ps[i].GetGetMethod();
if (mg != null)
{
ms = ps[i].GetSetMethod();
definedColumns.Add
(
new VirtualColumnInfo
(
ps[i].Name, ca.Width, ca.ReadOnly, ca.Title == String.Empty ? ps[i].Name : ca.Title,
ca.Format, mg, ms
)
);
}
break;
}
}
}
}
if (definedColumns.Count > 0)
columns = definedColumns.ToArray();
}
This extracts the public properties of the class and supplies marked items to the DataGridView as columns together with a header, format, etc.
The effect of all of this (and the rest of the missing code) was that any type could be virtualized in a dataGridView simply by tagging public properties and calling the virtualizer once for a given type:
#region Virtualisation
static readonly Virtualiser Virtual = new Virtualiser(typeof(UserRecord));
[XmlIgnore] // just in case!
public static int ColumnCount { get { return Virtual.ColumnCount; } }
public static VirtualColumnInfo ColumnInfo(int column)
{
return Virtual.ColumnInfo(column);
}
public Object GetItem(int column)
{
return Virtual.GetItem(column, this);
}
/*
** The supplied item should be a string - it is up to this method to supply a valid value to the property
** setter (this is the simplest place to determine what this is and how it can be derived from a string).
*/
public void SetItem(int column, Object item)
{
String v = item as String;
int t = 0;
if (v == null)
return;
switch (Virtual.GetColumnPropertyName(column))
{
case "DisplayNumber":
if (!int.TryParse(v, out t))
t = 0;
item = t;
break;
}
try
{
Virtual.SetItem(column, this, item);
}
catch { }
}
#endregion
The number of columns, their properties and order can be specified automatically by creating a number of public properties derived from the class data:
#region Display columns
[showColumn(ReadOnly = true, Width = 100, Title = "Identification")]
public String DisplayIdent
{
get
{
return ident;
}
set
{
ident = value;
}
}
[showColumn(Width = 70, Title = "Number on Roll")]
public int DisplayNumber
{
get
{
return number;
}
set
{
number = value;
}
}
[showColumn(Width = -100, Title = "Name")]
public string DisplayName
{
get
{
return name == String.Empty ? "??" : name;
}
set
{
name = value;
}
}
#endregion
This would virtualize any class for dataGridView to display and edit data and I used it many times over the years and the extraction of properties to display is exactly what is required for XML serialization, indeed, it has a lot of the same characteristics.
I was going to adapt this method to do the same job for XML serialization but someone has already done it at https://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=474453, I hope you can make use of this method to solve your problem.
This works for me:
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Entity entity = new Entity();
entity.CausedBy = new List<Entity>();
entity.CausedBy.Add(new Subclass1());
entity.CausedBy.Add(new Subclass2());
entity.CausedBy.Add(new Subclass2());
entity.CausedBy.Add(new Subclass1());
entity.CausedBy.Add(new Subclass1());
entity.Save(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Test.txt"));
}
}
[Serializable]
[XmlRoot("Entity")]
public class Entity
{
[XmlArray("CausedBy")]
[XmlArrayItem("SubClass1", typeof(Subclass1))]
[XmlArrayItem("SubClass2", typeof(Subclass2))]
public List<Entity> CausedBy { get; set; }
}
[Serializable]
[XmlRoot("Subclass1")]
public class Subclass1 : Entity
{
[XmlIgnore]
String t = DateTime.Now.ToShortDateString();
public String SubClass1Item { get { return "Test1 " + t; } set { } }
}
[Serializable]
[XmlRoot("Subclass2")]
public class Subclass2 : Entity
{
[XmlIgnore]
String t = DateTime.Now.ToString();
public String SubClass2Item { get { return "Test2 " + t; } set { } }
}
It produces:
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CausedBy>
<SubClass1>
<SubClass1Item>Test1 20/09/2017</SubClass1Item>
</SubClass1>
<SubClass2>
<SubClass2Item>Test2 20/09/2017 01:06:55</SubClass2Item>
</SubClass2>
<SubClass2>
<SubClass2Item>Test2 20/09/2017 01:06:55</SubClass2Item>
</SubClass2>
<SubClass1>
<SubClass1Item>Test1 20/09/2017</SubClass1Item>
</SubClass1>
<SubClass1>
<SubClass1Item>Test1 20/09/2017</SubClass1Item>
</SubClass1>
</CausedBy>
</Entity>

Cast IEnumerable to custom ObservableCollection Class?

Is it possible to convert IEnumerable to a Custom Class that is inherting from ObservableCollection class?
Reason is I want to select only a filtered set of items on the get. I want to implement it on the get because lots of other properties reference CustomItems and perform processes on the items, but I want to somehow make it process filtered set of items depending if a value is enabled or not.
Below is code to help explain what I want to achieve:
public class CustomItemsCollection : ObservableCollection<ItemViewModel>
{
public ListView ListView { get; set; }
public void ScrollToItem(object item = null)
{
//Some custom Code
}
}
And here is my property that I want to customize:
private CustomItemsCollection _CustomItems = null;
[JsonProperty]
public CustomItemsCollection CustomItems
{
get
{
if (_CustomItems != null)
{
if(SomeValueIsEnabled)
{
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue));
var castedItems = (CustomItemsCollection)filteredItems;
return castedItems;
}
return _CustomItems;
}
_CustomItems = new CustomItemsCollection();
_CustomItemsChangedSource = new CollectionChangedWeakEventSource();
_CustomItemsChangedSource.SetEventSource(_CustomItems);
_CustomItemsChangedSource.CollectionChanged += _CustomItemsChangedSource_CollectionChanged;
return _CustomItems;
}
set { _CustomItems = value; RaisePropertyChanged("CustomItems"); }
}
Specifically, this part:
if(SomeValueIsEnabled)
{
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue));
var castedItems = (CustomItemsCollection)filteredItems;
return castedItems;
}
Is this possible / or maybe wrong? What is the best practice to do it?
Thank you!
You can't just cast it, but you can create an instance of CustomItemsCollection and initialize it with filteredItems.
Add a constructor to your custom class that passes through to the appropriate ObservableCollection constructor:
public class CustomItemsCollection : ObservableCollection<ItemViewModel>
{
public CustomItemsCollection(IEnumerable<ItemViewModel> items)
: base(items) { }
// your other code here
}
Then you can do this:
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue));
var collection = new CustomItemsCollection(filteredItems);
return collection;
Try with this code:
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue))
.Select(pre=> new ItemViewModel(){
//add info here
});
var castedItems = new CustomItemsCollection(filteredItems);

C# Can I display an Attribute of an Object in a Dictionary as ListControl.DisplayMember?

The aim is to see the list as a list of 'name's.
Here's the dictionary:
class Scripts
{
public Dictionary<int, Script> scripts = new Dictionary<int, Script>();
...
}
Here's the attribute 'name' I'm after:
class Script
{
public string name { get; set; }
...
}
And here's the problem:
public partial class MainForm : Form
{
Scripts allScripts;
public MainForm()
{
InitializeComponent();
allScripts = new Scripts();
setupDataSources();
}
private void setupDataSources()
{
BindingSource ketchup = new BindingSource(allScripts.scripts, null);
//THIS LINE:
listBoxScripts.DisplayMember = allScripts.scripts["Key"].name.ToString();
listBoxScripts.ValueMember = "Key";
listBoxScripts.DataSource = ketchup;
}
...
}
I just can't think how to make that line work! Your advice is much appreciated!
Thanks
You can binding to Value and override ToString method in Script class.
private void setupDataSources()
{
BindingSource ketchup = new BindingSource(allScripts.scripts, null);
listBoxScripts.DisplayMember = "Value";
listBoxScripts.ValueMember = "Key";
listBoxScripts.DataSource = ketchup;
}
Script class:
class Script
{
public string name { get; set; }
public override string ToString()
{
return name;
}
}
You're setting the actual value of 'name' as the DisplayMember, so unless you randomly get a value in 'name' set to the same text as a property then you'll never get it displayed.
You'd be better off just doing:
listBoxScripts.DisplayMember = "name";
Surely?
Try casting the dictionary element as a Script object
listBoxScripts.DisplayMember = ((Script)allScripts.scripts["Key"]).name.ToString();

How to design collection in C#

I have a class MySet
class MySet
{
.......
}
This class will declare a reference to another type
(i.e)
class MySubSet
{
....
}
The purpose of the type MySubset is to supply "subset id" and a collection of integers to
the type MySet.
Which one of the followings is the correct implementation
(1)
class MySet
{
int mySetID;
MySubSet subset = new MySubSet();
public int MySetID
{
get { return mySetID; }
set { mySetID = value; }
}
public MySubSet MySubSet
{
get { return subset; }
set { subset = value; }
}
}
class MySubSet
{
int subsetID;
List<int> subset = new List<int>();
public List<int> SubSet
{
get { return subset; }
set { subset = value; }
}
public int SubSetID
{
get { return subsetID; }
set { subsetID = value; }
}
}
(2)
class MySet
{
int mySetID;
AnotherSubSet subset = new AnotherSubSet();
public int MySetID
{
get { return mySetID; }
set { mySetID = value; }
}
public AnotherSubSet MySubSet
{
get { return subset; }
set { subset = value; }
}
}
class AnotherSubSet : List<int>
{
int subsetID;
List<int> lst = new List<int>();
public int SubSetID
{
get { return subsetID; }
set { subsetID = value; }
}
}
If both are worst design consideration help me to implement the one that I could follow.
MySet doesn't look like a collection to me. It's just a class.
I'd rename it to ´MyEntity´or something like that.
List<MyEntity> mySet = new List<MyEntity>();
From all the information you've provided, I would do this:
public class MyEntity
{
public int ID { get; set; } // shortcut
public List<int> Numbers = new List<int> { get; set; } // shortcut
}
Sorry, I don't have /Net3.0 to hand so can't check the constructor of the list with the shortcut get/set but its the theory that counts...
The first version is better (as improved upon by ck) - use composition instead of inheritance. You are advised not to add properties to collections, which is effectively what you're doing in version 2. Collections should contain their items only. Someone else may be able to expand on the reasons for this, as I am not an expert, but it does cause serialization problems.
Number 2 is better, use inheritence not composition for this pattern, - because fundementally, it is a collection. It does not contain a collection. Inheritance gives you all the functionality of the base class without the need to write pass-through functions. If you want to add a new item to the collection, using composition, you either have to add a pass through method for the Add() method to class MySubSet:
class MySubSet
{
int subsetID;
List<int> subset = new List<int>();
public List<int> SubSet
{
get { return subset; }
set { subset = value; }
}
public void Add(int i) { subset.Add(i); } // pass through to subset.Add()
}
or you have to use the following non-intuitive and confusing syntax...
MySet.MySubSet.SubSet.Add(67);
with inheritence, all you need is
MySet.MySubSet.Add(67);

Categories

Resources