String behaviour during ordering data - c#

In my application I download some data from website providing landscape informations like population, landscape area and few more.
After parsing html code, data are stored in list of objects
public class Landscape
{
public int Population { get; set; }
public string Area { get; set; }
}
public List<Landscape> data;
No problem with that. Follows filling dataGrid and that's purpose of my application. Now, where is the problem? Area info on the website is in semi-numeric, semi-string format. For example: 10 000 km2.
I have possibility to choose whether to trim km2 suffix and store data as int, or do nothing about it and store data as string. Since I want have data in dataGrid in original format, I decided not to trim.
Finally, is there a way to order rows (by size of area) as int although it is string type?

You can use linq to sort by the translated value but don't think this will be fast.
public class Landscape
{
public int Population { get; set; }
public string Area { get; set; }
public int TrimAndConvert()
{
/* Your Code to trim and convert to int */
}
}
data.OrderBy(landscape => landscape.Area.TrimAndConvert());
I think a better way would be to save the Area as a number and add the trimmed part just for output.
public class Landscape
{
public int Population { get; set; }
public int AreaValue { get; set; }
public string AreaUnit { get; set; }
public string Area
{
get
{
return AreaValue.ToString() + AreaUnit;
}
}
}

You will need to implement an IComparer and pass and instance of it to the List.Sort() method/overload that takes an IComparer.
This should get you started:
List<T>.Sort Method (IComparer<T>)

Related

how to fill DataGridView with json lis

Hi I am using this function to show json in DataGridView but the problem is I have a list in the json file , this list doesn't display data in the grid
void show_data()
{
dataGrid.Columns.Clear();
dataGrid.DataSource = all_date;
}
my json file is as this
[{"Name":"350SC250-14","Fy":33.0,"GFy":false,"T":0.0713,"GT":false,"D":2.5,"Stud_D":1.5,"C":0.0,"B":3.5,"GB":false,"Manufacturer":"BIDDLE","CFS_File":"350SC250-14.cfss","Sub_SectionCount":0,"Sub_Section1":"","Sub_Section2":"","Sub_Section3":"","SectionType":3,"Configuration":0,"SectionParts":[{"Length":0.375,"Radius":0.1069},{"Length":0.5,"Radius":0.1069},{"Length":3.0,"Radius":0.1069},{"Length":0.5,"Radius":0.1069},{"Length":0.5,"Radius":0.1069},{"Length":2.5,"Radius":0.1069},{"Length":0.5,"Radius":0.1069},{"Length":0.5,"Radius":0.1069},{"Length":3.0,"Radius":0.1069},{"Length":0.5,"Radius":0.1069},{"Length":0.375,"Radius":0.0}]}]
my class is bellow
class dataForm
{
public string Name { get; set; }
public double Fy { get; set; }
public bool GFy { get; set; }
public double T { get; set; }
public bool GT { get; set; }
public double D { get; set; }
public double Stud_D { get; set; }
public double C { get; set; }
public double B { get; set; }
public bool GB { get; set; }
public string Manufacturer { get; set; }
public string CFS_File { get; set; }
public int Sub_SectionCount { get; set; }
public string Sub_Section1 { get; set; }
public string Sub_Section2 { get; set; }
public string Sub_Section3 { get; set; }
public int SectionType { get; set; }
public int Configuration { get; set; }
public List<SectionPart> SectionParts { get; set; }
}
class SectionPart
{
public double Length { get; set; }
public double Radius { get; set; }
}
so how can I diplay this sectionPart list ?
Add Newtonsoft.Json nuget :Install-Package Newtonsoft.Json to your project, and convert JSON to object using DeserializeObject
string data_from_json = #"[{'Name':'350SC250 - 14','Fy':33.0,'GFy':false,'T':0.0713,'GT':false,'D':2.5,'Stud_D':1.5,'C':0.0,'B':3.5,'GB':false,'Manufacturer':'BIDDLE','CFS_File':'350SC250 - 14.cfss','Sub_SectionCount':0,'Sub_Section1':'','Sub_Section2':'','Sub_Section3':'','SectionType':3,'Configuration':0,'SectionParts':[{'Length':0.375,'Radius':0.1069},{'Length':0.5,'Radius':0.1069},{'Length':3.0,'Radius':0.1069},{'Length':0.5,'Radius':0.1069},{'Length':0.5,'Radius':0.1069},{'Length':2.5,'Radius':0.1069},{'Length':0.5,'Radius':0.1069},{'Length':0.5,'Radius':0.1069},{'Length':3.0,'Radius':0.1069},{'Length':0.5,'Radius':0.1069},{'Length':0.375,'Radius':0.0}]}]";
dataGrid.Columns.Clear();
List<dataForm> all_date = JsonConvert.DeserializeObject<List<dataForm>>(data_from_json);
dataGrid.DataSource = all_date;
to display SectionParts only:
dataGrid.DataSource = all_date[0].SectionParts;
The problem you describe does not really have anything to do with JSON. The problem is with the Class dataForm. I do not like to say “problem” since the issue is fairly easy to understand, once you understand what your code is asking from the grid. The issue is that when the grid is given a DataSource like a List<T> or List<dataForm>, the grid will obligingly map each “primitive” property of the dataForm class (or any class T) to a column in the grid.
The grid is going to have to do something different when it comes across a property in the class that is a “Collection” or another “Class”. In this case, dataForm has a “collection” property …
public List<SectionPart> SectionParts { get; set; }
In this case the grid is not sophisticated enough to figure this out. It really is not going to know how to put “multiple” values into a single cell. Therefore, the grid will ignore collections as you obviously already know. This same Idea applies if the property in the class is another class… it will not display it.
Bear in mind, as other have commented, there are third-party controls that may have features that will show the collections or classes. Unfortunately, the out of the box DataGridView is fairly limited. In most cases, the easiest way to deal with this is in a “Master/Detail” type display, where the first grid displays the class and the second grid displays the collection of the “selected” item in the first grid.
With that said, there are ways to achieve your goal without a lot of work depending on “how” you want to “display” the data to the user. IMHO a master-detail is usually the easiest to implement and is user friendly. Another option, is to “flatten” each of the items in the collection creating a column(s) for each item in the collection. This is much more work and you will possibly end up with many columns and many empty cells… not user friendly. The last option which may work for your case is to create a public property in the dataForm class that “exposes” the SectionParts collection as a single string.
Example: in this case, the SectionPart class has two (2) properties.
public double Length { get; set; }
public double Radius { get; set; }
To help later, let’s override the ToString method to return the two values as a single string. Something like…
public override string ToString() {
return "L: " + Length + " R: " + Radius;
}
Moving to the dataForm class there is a “collection” of the SectionPart objects. To display ALL the section parts into a single cell we need to create a single string from ALL the section parts. Each part will be on a single line using the SectionParts ToString method we added above. To make this “single” string display in the grid, we need to add a new property to the dataForm class that returns this “list of parts” as a single string. This property may look like…
public string SectionPartsList {
get {
StringBuilder sb = new StringBuilder();
foreach (SectionPart sp in SectionParts) {
sb.AppendLine(sp.ToString());
}
return sb.ToString();
}
}.
You may need to adjust the grids rows height to accommodate, however, in my test, if you simply hover your cursor over the cell the list will display.
Lastly, for completeness, let us assume, that instead of a “List” of SectionParts the class had a single instance of this class.
public SectionPart SingleSectionPart { get; set; }
Again the grid is going to ignore this “class” property when creating the columns in the grid. However, if you wanted those two fields displayed in the grid, then it would be fairly simple to create two properties in the dataForm class that simply return those values. In this case, the two properties may look like…
public double SP_L {
get {
return SingleSectionPart.Length;
}
}
public double SP_R {
get {
return SingleSectionPart.Radius;
}
}
I hope this makes sense and helps.

How to handle data modification in C# XAML WPF

The issue
Ok Hey guys, my issue is currently trying to think of the best way to edit data that exists in my application written in c# using WPF.
The application is small standalone app that uses XML to store rules on how to interpret hex messages and display it in human readable format.
Currently my app works fine, but i manually crafted the XML, i want to write something in the app that will allow layman users to make their own rule sets and save them to XML.
Now the saving to XML and the handling of the data once edited i am sure i can do, but i'm stumped over the best approach for XML.
Ok for brevity im just giving the general info and exluding some stuff - the classes i'm working with:
Rulesets
public class RuleSet
{
public string Name { get; set; }
public string LongName { get; set; }
public DateTime ReleaseDate { get; set; }
public string Base { get; set; }
public List<String> IncludedBulletins { get; set; }
public List<Byte> Bytes { get; set; }
public RuleSet(string name, string longName, string releaseDate, string #base)
{
ReleaseDate = parseDate(releaseDate);
Name = name;
LongName = longName;
Base = #base;
IncludedBulletins = new List<String>();
Bytes = new List<Byte>();
}
}
Bytes
public class Byte
{
public int ID { get; private set; }
public ReadMode Mode { get; private set; }
public List<Rule> Rules { get; set; }
public enum ReadMode
{
ASSORTED,
MULTI,
SINGLE
};
public Byte()
{
Rules = new List<Rule>();
}
}
Rules
public class Rule
{
public bool Active { get; private set; }
public int BytePos { get; private set; }
public int NibblePos { get; private set; }
public int Bit { get; private set; }
public int EndBit { get; private set; }
public int Value { get; private set; }
public int EndValue { get; private set; }
public string Translation { get; private set; }
public bool AllLowerBits { get; private set; }
public Rule()
{
Active = false;
Translation = "RFU";
}
}
Here is an example of the rules we interpret:
For Background info this is a Cardholder Verfication Method Rule passed in Banking applications between devices in Hexadecimal format and to interpret it is as described there.
I have a Catalog which is a list of rulesets stored in memory when the application loads initially it loads all the XML and parses it into the objects above which can then be interacted with in the app to provide meaningful information.
What i am struggling with is the best UI display i can make, i have considered a :
Treeview - with the rulesets and the children being the Bytes, display the properties for a ruleset in the upper part of a form, and when the user clicks on a byte it populated a section listing rules that can be added to with a new button that allows new rules to be made. This would require figuring out how to add a new byte to the treeview and allowing ordering of the treeview so the byte is correctly placed / maneuvered.
Listview With the rulesets only and data being displayed in a form as before but with tabcontrol for each byte, again this would require figuring out how to add a new byte to the treeview and allowing ordering of the treeview so the byte is correctly placed / maneuvered.
Something else you guys can suggest?
If anyone has any examples or links to tutorials for the needed things in the list or a better suggestion and examples that would be great I'm largely paralyzed trying to think of the best way to handle this data.

What columns are available for the prediction/output class in ml.net

I'm running binary classifiers in ML.net. The output class looks like below, it has a "PredictedLabel" and through trial and error I've discovered the that "score" and "probability" are also valid. Where are the valid properties documented? And is there a property that I can use (with a corresponding name on the input data class) that will allow me to store a row id on the input data that will be output with the prediction?
Thanks
public class TargetData
{
[ColumnName("PredictedLabel")]
public bool Value { get; set; }
public float Score { get; set; }
public float Probability { get; set; }
}
ML.NET relies on schema comprehension to map the fields of an object to columns of a data view and back.
There is no limit on which columns your data view may have. For example, you could define your example class to be
public class Example
{
// Let's say your features are floats:
public float FeatureA;
public float FeatureB;
// ...
public bool Label;
// Here's an arbitrary RowId column.
public string RowId;
}
The RowId column will be created, and propagated all the way through the training, and it will be retained in the resulting model.
In order to read it back, just declare the field/property with the same name in your output class:
public class TargetData
{
[ColumnName("PredictedLabel")]
public bool Value { get; set; }
public float Score { get; set; }
public float Probability { get; set; }
public string RowId { get; set; }
}
The only limitation is on the allowed types: for example, you cannot declare GUID fields etc. The schema comprehension doc and the other linked docs define precisely which types are allowed.

Is there a way to "kill" a Model Property?

My application's front end is a DataGrid whose contents are passed to an Excel-generating method.
The catch is that the DataGrid deals with 13 columns: 10 of them are fixed (i.e., passed to Excel) while each of the last 3 is optional.
public class GridModel
{
public string Item { get; set; }
public string ItemName { get; set; }
public double TotalHeight { get; set; }
public double AGLheight { get; set; }
public double Embedment { get; set; }
public string Shape { get; set; }
public double TipDiameter { get; set; }
public double BaseDiameter { get; set; }
public double Taper { get; set; }
public double ShearReaction { get; set; }
// The following are optional, in 8 combinations, from all present to all absent
public double Camber { get; set; }
public double Rake { get; set; }
public double Angle { get; set; }
}
Being a C# newbie, I am considering the different approaches.
How would you folks deal with this? The simplest idea that comes to mind is to add 3 flags to the model:
bool IsColumn1Present;
bool IsColumn2Present;
bool IsColumn3Present;
Another way would be to add a level to the hierarchy, so each of the 'special' columns contains its own embedded flag:
if (Camber.flag) add(Camber.value);
That said, I would like to have the ability to somehow remove those 3 properties, so any attempt to access them would result in an error or impossibility.
If such thing exists, I guess it would be called "Variant Properties".
TIA
Note: I have solved this already by the manipulation of the Visibility.Visible field at the GUI level. Gurus, however, tell us that this is a bad idea. Best practices dictate that this facility should be part of the Model.
You could use nullable properties:
public double? Camber { get; set; }
Then check them for a value in your business logic:
if (thing.Camber.HasValue)
{
DoSomething(thing.Camber.Value);
}
It sounds like this might be exactly what you're after, given your comment on "variant" properties.
More info: http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx
Update: If you need to switch them off application-wide (as per your comment), you could either avoid setting the value in the first place when it's not wanted (this would be preferable as this is, as far as I'm concerned, business logic and doesn't belong in your dumb model classes) or extend this with a custom accessor:
private double? _camber;
public double? Camber
{
get
{
return ModelSettings.CamberEnabled
? _camber
: null;
}
set;
}
Then have some static/constant property somewhere:
public static class ModelSettings
{
public const bool CamberEnabled = true;
}
If the number of columns is constant (meaning the user can't add 'custom' columns), I would suggest a bit-field enum value like so:
[Flags]
public enum ColumnFlags
{
None = 0,
Camber = 0x1,
Rake = 0x2,
Angle = 0x4,
// Other optional columns here, keep them powers of 2!
}
Then in your Model class, keep a value such as:
public ColumnFlags ColumnFlags { get; set; }
Then you can use...
if(model.ColumnFlags.HasFlag(ColumnFlags.Camber))
{
// Do something here...
}
if(model.ColumnFlags.HasFlag(ColumnFlags.Rake))
{
// Do something here...
}
EDIT: Alternatively, you can use the Nullable<T> types to specify a "missing" or "empty" value.

Reducing Ajax data footprint by binding on a DataTable with nested objects?

There seems to be many questions relating to binding on a DataTable, but none that I could find touch on my exact situation.
I'm currently ajax binding on a list of objects like such:
public class MyObject
{
public string Name { get; set; }
public string Something1{ get; set; }
public string Something2{ get; set; }
public string Something3 { get; set; }
public MyObjectMyObject2 { get; set; }
}
public class MyObject2
{
public string Color { get; set; }
public string Something4 { get; set; }
}
[GridAction]
public ActionResult GetData()
{
var data = QueryDatabaseAndInstantiateAListOfMyObjects();
return View(new GridModel(data));
}
And with a view like such:
<%= Html.Telerik().Grid<MyObject>()
.DataBinding(dataBinding => dataBinding.Ajax().Select("GetData", new { action = "GetData" }))
.Name("Grid1")
.Columns(columns =>
{
columns.Bound(o => o.Name).Title("Name1");
columns.Bound(o => o.MyObject2.Color).Title("Color");
columns.Bound(o => o.Something1).Hidden(true);
columns.Bound(o => o.Something2).Hidden(true);
columns.Bound(o => o.Something3).Hidden(true);
columns.Bound(o => o.MyObject.Something4).Hidden(true);
})
%>
This works great and all as I'm able to sort, group, and all the above.
My situation is I have many properties on MyObject and some edges cases are popping up that are yielding a couple megabytes of response data. The reason being there are many many hidden columns that are situational dependent that a user can right-click to show. The problem is, data for all these extra hidden columns are included in the response data even when they're not used per say. And since the act of grouping, un-grouping, showing and hiding columns fetches for data anyways, why does all the extra data have to come with it?
If I could have only the data returned that is necessary to populate the visible columns plus say a couple that I could mark somehow with a custom attribute, that would immensely help cut back on the size of the returned data.
So I took to converting my list of objects to a DataTable that I could then conditionally add columns + data for and then feed that to the GridModel. This worked well up until trying to group by a column that is in a nested object such as o.MyObject2.Color.
I run into this exception:
Property with specified name: MyObject2.Color cannot be found on type: System.Data.DataRowView
I guess this makes sense, but how do I overcome this? When I use Object Shredder, it sets each property of MyObject loosely typed such as ["Name"] as a string and ["MyObject2"] as a MyObject2. But everything past ["MyObject2"] is strongly typed: (dataRow["MyObject2"] as MyObject2).Color. And this is where is gets over my head.
Is there another way to overcome my initial issue of all that extra data being sent that isn't used? Or, is there any advice with the DataTable bit? I've also tried converting the DataTable to a IEnumerable with no such luck. The serialized Json is quite empty. I've also tried flattening all nested objects such as having datarow["MyObject2.Color"] as string, but this wreaks havok when referencing this column in JavaScript so I had to go with an underscore delimiter ["MyObject2_Color"] but this really screws up binding Columns in the UI. There has to be a way!
I don't see any reason to bring back your full object just to show Color and Something4. Try flattening it out. Something like this where you just assign the values of Color and Something4 to the properties of the model.
public class MyObject
{
public string Name { get; set; }
public string Something1{ get; set; }
public string Something2{ get; set; }
public string Something3 { get; set; }
public string Something4 { get; set; }
public string Color { get; set; }
}
[GridAction]
public ActionResult GetData()
{
var data = QueryDatabaseAndInstantiateAListOfMyObjects();
data.Something4 = MyObject2.Something4;
data.Color = MyObject2.Color;
return View(new GridModel(data));
}
This is the true Answer, but I'm giving credit to Alfalfa for the idea.
I continue along with the DataTable idea, but use getters to expose each nested object property. It's a bit conveluded and brittle, but it works!
public class MyObject
{
public string Name { get; set; }
public string Something1{ get; set; }
public string Something2{ get; set; }
public string Something3 { get; set; }
[ScriptIgnore()]
public MyObjectMyObject2 { get; set; }
public string Color { get { return this.MyObject2.Color; } }
public string Something4 { get { return this.MyObject2.Something4; } }
}
public class MyObject2
{
public string Color { get; set; }
public string Something4 { get; set; }
}

Categories

Resources