Sorting a DataGridView by DateTime - sorting

I have a website that is written in asp.net using C#. grdStatus is an instance of System.Windows.Forms.DataGridView. It displays 2 columns -- StatusDate and Status. StatusDate contains DateTime values. Status contains strings. The problem is that when the grid is sorted on StatusDate, it does not sort the values as DateTimes. Honestly, I'm not quite sure how it's sorting them. When I click on the Status Date column header, it sorts the dates like this:
Status Date
9/24/2014 10:01:06 AM
9/24/2014 10:00:58 AM
9/23/2014 7:27:23 PM
9/1/2015 4:48:35 PM
10/22/2014 12:15:38 PM
10/22/2014 12:15:29 PM
10/22/2014 12:12:52 PM
10/22/2014 12:12:27 PM
It's certainly not sorting them by DateTime, but it doesn't seem to be sorting them alphabetically, either. Here's the method that refreshes the grid. I added the two lines indicated by ---> in an attempt to force it to sort the rows by DateTime, but they seem to have no effect.
private void RefreshGrid()
{
IEnumerable<OrderService.OrderDetailStatus> statusItems = services.OrderSvc.GetStatusHistoryForOrderDetail(OrderDetailId);
IEnumerable<ViewModels.StatusHistoryGridViewModel> gridItems = AutoMapper.Mapper.Map<IEnumerable<ViewModels.StatusHistoryGridViewModel>>(statusItems);
grdStatus.AutoGenerateColumns = false;
grdStatus.DataSource = gridItems.ToDataTable<ViewModels.StatusHistoryGridViewModel>();
--->grdStatus.Columns[0].ValueType = typeof(DateTime);
--->grdStatus.Sort(grdStatus.Columns[0], ListSortDirection.Ascending);
}
Here's the view model that's being used as the data source for the grid. As you can see, CreatedDate (which is mapped to StatusDate) is a DateTime member.
namespace IVGOffice.ViewModels
{
public class StatusHistoryGridViewModel
{
public string StatusName { get; set; }
public DateTime CreatedDate { get; set; }
}
}
I've looked at some other posting related to this, but I haven't found anything that helps. Can anyone explain to me how to get this to sort correctly?

Part of the problem was that I was overlooking that fact that one of the dates had a different year from the others. After I noticed that, I was able to get the control to sort the column by the date; however, I still wasn't able to get it to sort by both date and time. I think this may be a bug in the DateGridView control. I replaced it with an UltraGrid control from Infragistics and that worked correctly.

Related

LINQ: Finding an item in a List which contains List of items

guys!
I have a small issue with LINQ (Im total beginer in this topic). Maybe it is some desing mistake, but let you decide it.
I'm coding a Windows Store App, which is kind a calendar. It has a Day object. Because of the semantic zoom (and some groupping hack), I put this Day into a wrapper class, named as Month.
After loading all data, and after getting the current data, I want to extract from this structure the current Day object.
Here is the important code:
public class Day
{
public int nr { get; set; }
...
}
public class Month
{
public string Title {get;set;}
public List<Day> Days{get;set;}
}
Later I have this:
List<Month> Months;
It is correctly filled with lists of days. Now comes the tricky part:
Day Today = Months.Find( ??? )
I had some idea, but none of them was statisfying...
So, the question is:
How can I select an item from a multiple list hierarchy in LINQ?
(List<List<Day>>, and one condition must met in each list (Day.nr and Month.nr))
Create an Enum for every month:
public enum NamesOfMonths
{
January = 1,
February = 2,
// so on and so forth
}
Now, you can use it to find the correct Month, and eventually the correct Day.
var dayToday = DateTime.Now.Day;
var monthToday = DateTime.Now.Month;
Day Today = Months.Find(m => m.Title.Equals(((NamesOfMonths)monthToday).ToString()))
.Days.Where(d => d.Nr == dayToday).FirstOrDefault();
I think you're looking for SelectMany:
var days = months.SelectMany(m => m.Days); // Gets all the days in those months
var today = days.Where(d => /* some condition goes here */);

Telerik OpenAccess - Search With Non-Persistent Property

I'm using Telerik OpenAccess and SQL Server on a project and I need to be able to search by what someone's age will be on a certain date. The problem that I am running into is that the person's date of birth is stored in one table and the date to compare to is in another table, which prevents me from using a computed column. They are, however, joined together so that I can calculate the age by creating my own non-persistent property in the partial class like so:
public partial class Student
{
[Telerik.OpenAccess.Transient]
private int? _ageUponArrival;
public virtual int? AgeUponArrival
{
get
{
try
{
var dob = DateTime.Parse(this.StudentProfiles.First().Person.YearOfBirth);
var programStart = (DateTime)(this.StudentPrograms.First().ProgramStart);
this._ageUponArrival = programStart.Year - dob.Year;
if (dob > programStart.AddYears(-(int)(this._ageUponArrival)))
{
(this._ageUponArrival)--;
}
}
catch (Exception e)
{
this._ageUponArrival = null;
}
return _ageUponArrival;
}
set { }
}
}
Please ignore how bad the tables are set up, it's something that I inherited and can't change at this point. The problem with this approach is that the property is not available to search on with Linq. I know that I could create a view that would do this for me, but I would much rather not have to maintain a view just for this. Is there any way at all to create a calculated property through Telerik that would be calculated on the db server in such a way as to be searchable?
It appears that this is not possible at this point. http://www.telerik.com/community/forums/orm/linq-questions/dynamic-query-with-extended-field.aspx

Get single value from XML and bind it to a textblock?

Trying to create a prayer time app for prayertimes in Oslo. I have a XML file located in the app.
What i want to do:
Based on month and the day, get value for morning prayer, evening prayer and so on.
I want one value at a time, and show it in a textblock. how do i do it?
I am currently getting the info in a listBox but i rather want the single value to be shown in a textblock. Or should i use some other thing?
public class PrayerTime
{
public string Fajr { get; set; }
public string Sunrise { get; set; }
}
To get the value:
XDocument loadedCustomData = XDocument.Load("WimPrayerTime.xml");
var filteredData = from c in loadedCustomData.Descendants("PrayerTime")
where c.Attribute("Day").Value == myDay.Day.ToString()
&& c.Attribute("Moth").Value == myDay.Month.ToString()
select new PrayerTime()
{
Fajr = c.Attribute("Fajr").Value,
Soloppgang = c.Attribute("Soloppgang").Value,
};
listBox1.ItemsSource = filteredData;
Also i want to know how best the XML should be set up for this purpose.
Like this:
<PrayerTime>
<Day>1</Day>
<Month>5</Month>
<Fajr>07:00</Fajr>
<Sunrise>09:00</Sunrise>
</PrayerTime>
Or like this:
<PrayerTime
Day ="1"
Month="5"
Fajr="07:00"
Sunrise="09:00"
/>
yourTextBox.Text = filteredData.First().Fajr;
As to know whether it's best to put information in a XML file as attributes or nodes, that's a recurrent question with no definite answer. In most cases, it's just a matter of taste.

Conditional Calucations with MVC4

I am trying to conditionally calculate some values based on user inputs in a form. The "inputs" themselves tie into the calculation, in that if a user is presented with two radio button lists their selections will determine whether or not a currency amount is attached, and then later added together. I don't understand jquery, and so I cannot figure out how to use something like knockout.js to do what I want (besides, my calculation will be served up in a confirmation view only and will not be "re-calculated" unless the user goes back and changes their selections).
Note, I am not talking about the scenario where you have a textbox that accepts a value and adding it to another textbox value the user inputs (e.g., user enters 10, then 10, then form calculates 20). The values are static based upon selection.
For context, I am using Serializer and a wizard which is stepping through and passing model selections/inputs to the subsequent view.
I can do something like this as an example (it's simple, but based on responses I can figure out how to build it up to the more complex scenario I have):
Model.cs:
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:c}")]
public decimal calculated { get; set; }
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:c}")]
public decimal option1 = 500;
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:c}")]
public decimal option2 = 100;
//Following is just my idea to calculate $0 if
//a selection results in a "no value option"
//although I suppose if nothing is selected I
//can just avoid calculating + $0
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:c}")]
public decimal nooption = 0;
Then in Confirm.cshtml:
#{
Model.calculated = Model.option1 + Model.option2 + Model.nooption;
}
....
#Html.DisplayFor(m => m.calculated)
will display $600.00. That's easy enough.
However, my goal is threefold. First, I need to tie in, for example, option1 with the selection from a radiobutton list, and option2 with another radiobutton list depending on what the user selects. Second, depending on the selection I want to conditionally calculate all the options present which will obviously vary based on user selection (some users will select option1 and option2, others just option1, others just option2, still others neither). Third, where is the best place to have the calculation take place (the view, a .cs file, the controller (although I am trying to minimize code there), etc.).
So, if I have these enums for the radiobutton lists (each option corresponding to an option for now, later I will discuss two options per radiobutton list enum):
public enum radio1
{
radio1selection1, // this would correspond to nooption (or $0)
radio1selection2 // this would correspond to option1 (or $500)
}
public enum radio2
{
radio2selection1, // this would correspond to nooption (or $0)
radio2selection2 // this would correspond to option2 (or $100)
}
I've indicated in the enums how I'd like to "tie" the option to the selection.
My problem is in trying to do if statements, which I cannot figure out properly. Something like this in Confirm.cshtml:
#{
if (Model.radio1 == radio1selection1)
Model.calculated = Model.nooption;
else....
}
The above is completely wrong, I know. I am trying to think of all the permutations of calculating, but I don't think its worth the effort because it would either be wrong or it would work but be too long when there is an easier way. I was even thinking of trying case/break but that too seems oddly the wrong approach.
What's adding to the complexity for me is if my enums have more than two selections, and those other selections result in several options, say option1 and option1a, and depending on which the user selects will determine the calculation. So the enum becomes:
public enum radio1
{
radio1selection1, // this would correspond to nooption (or $0)
radio1selection2, // this would correspond to option1 (or $500)
radio1selection3 // this would correspond to NEW
// option1a (or $750) (with a corresponding
// "int" named "option1a")
}
One of the things I thought of doing was to just display all the options selected in a <table> in the view, so that even if something is a $0 value, it would just say $0 as the option. Then I thought I could just add all the values present. But still I don't know the best way to accomplish that.
Any opinions on how I would be able to and or all three of my stated goals above?
I would define the property as follows:
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:c}")]
public decimal calculated { get { return option1 + option2 + option3; } }
You can make the logic as conditional as necessary inside the getter. I think model is the best place for those calculations, which is what we get with the calculated property.
To render a collection of options, define them as follows:
public class MyOption
{
public string ID { get; set; }
public string Name { get; set; }
}
List<MyOptions> options = new List<MyOptions>();
options.Add(new MyOption { ID = "1", Name = "First" });
model.Options = options;
You can have a method instead of the Options property that returns a list of options based on the data of the option* properties.
Then convert it to a SelectList object in some helper method. An HTML helper can be defined as follows:
public static class MyHelperExtensions
{
public static SelectList MyOptionList(this HtmlHelper helper, List<MyOptions> options)
{
return new SelectList(options, "ID", "Name");
}
}
In the view, use the following code to render the options:
#Html.DropDownListFor(x => x.MyOptionProperty, Html.MyOptionList(Model.Options))
I figured out how to do this (might not be clean/efficient/standard practice, but it got the job done):
Model.calculated =
Model.PriceQuote.priceChapter7Solution +
((Model.radiobuttonlist1 ==
Namespace.ViewModels.MyModel.radio1.radio1selection1) ?
Model.option1 :
(Model.radiobuttonlist1 ==
Namespace.ViewModels.MyModel.radio1.radio1selection2) ?
Model.option2 :
Model.nooption);
I could just add + after ... : Model.nooption) instead of ending the statement with ; to calculate conditions on other options.
Originally I did not know that the conditional (? :) operator could contain more than two expressions - i.e., it's right associative so additional conditions will be evaluated as a ? b : (c ? d : e). See Docs.

MongoDB C# low performance issue

I'm testing MongoDB 1.6.5 speed and C# in win64 machine. I use Yahoo.geoplanet as source to load states, county, towns but i'm not very performant. I have currently more 5 sec to load the US states from these source passing a List to a web page in localhost.
Use only id as index. Can someone suggest way to perform. Thanks
class BsonPlaces
{
[BsonId]
public String Id { get; set; }
public String Iso { get; set; }
public String Name { get; set; }
public String Language { get; set; }
public String Place_Type { get; set; }
public String Parent_Id { get; set; }
}
public List<BsonPlaces> Get_States(string UseCountry)
{
using (var helper = BsonHelper.Create())
{
var query = Query.EQ("Place_Type", "State");
if (!String.IsNullOrEmpty(UseCountry))
query = Query.And(query, Query.EQ("Iso", UseCountry));
var cursor = helper.GeoPlanet.PlacesRepository.Db.Places
.FindAs<BsonPlaces>(query);
if (!String.IsNullOrEmpty(UseCountry))
cursor.SetSortOrder(SortBy.Ascending("Name"));
return cursor.ToList();
}
}
I suppose problem not in mongodb, loading can be slow for two reasons:
You trying to load big count of 'BsonPlaces'(20000 for example or even more).
Some another code on page take much time.
For speed improvements you can:
1.Set limit to items that will be returned by query:
cursor.SetLimit(100);
2.Create indexes for 'Name', 'Iso', 'Place_Type':
helper.GeoPlanet.PlacesRepository.Db.Places.EnsureIndex("Name");
c# driver probably have big performance problem. A simple query for 100k times on shell takes 3 seconds, same query (written in c# linq of official c# driver 1.5) takes 30 seconds. Profiler tells each query from c# client takes less than 1 ms. So I assume c# driver is doing a lot of unnecessary stuffs that makes the query so slow.
Under mongodb 2.0.7, OS: windows 7, Ram: 16G.
I downloaded the GeoPlanet Data from Yahoo and found that the geoplanet_places_7.6.0.tsv file has 5,653,969 lines of data.
That means that in the absence of an index you are doing a "full table scan" of over 5 million entries to retrieve the 50 US states.
When querying for states within a country, the following index would probably be the most helpful:
...EnsureIndex("Iso", "Place_Type");
Not sure why you would want to search for all "States" without specifying a country, but you would need another index for that.
Sometimes when a sort is involved it can be advantageous for the index to match the sort order. For example, since you are sorting on "Name" the index could be:
...EnsureIndex("Iso", "Place_Type", "Name");
However, with only 50 states the sort will probably be very fast anyway.
I doubt any of your slow performance is attributable to the C# driver, but if after adding the indexes you still have performance problems let us know.

Resources