List<SelectListItem> Selected Value somehow set on both ViewBag - c#

I am trying set selected value to 2 List to show them on DropDownList in View.
I don't know why but StartDate also have EndDate selected value instead of the one I set it.
Controler
List<SelectListItem> StartDate = new List<SelectListItem>();
StartDate = lst;
if (StartDate.Count > 0)
{
StartDate[0].Selected = true;
System.Diagnostics.Debug.WriteLine("Start Date: " + StartDate[0].Text);
}
ViewBag.ListStartDate = StartDate;
//For EndDate, set "Select" for the last Entry
List<SelectListItem> EndDate = new List<SelectListItem>();
EndDate = lst; //lst is the default list without any select set to true
if (EndDate.Count > 0)
{
EndDate[EndDate.Count - 1].Selected = true;
System.Diagnostics.Debug.WriteLine("End Date: " + EndDate[EndDate.Count - 1].Text);
}
System.Diagnostics.Debug.WriteLine("[Finished End Info]");
ViewBag.ListEndDate = EndDate;
View
End Date
#Html.DropDownList("DateStartDropList", (List<SelectListItem>)ViewBag.ListStartDate)
Start Date
#Html.DropDownList("DateEndDropList", (List<SelectListItem>)ViewBag.ListEndDate);

StartDate = lst;
Please check the lst, I assume it should be a list of SelectListItem, right? If that is the case, the issue might relate that. Please refer the following sample:
If the lst is a list of SelectListItem, try to modify the code as below:
StartDate = lst.Select(c => new SelectListItem() { Value = c.Value, Text = c.Text, Selected = c.Selected }).ToList();
The updated code like this:
List<SelectListItem> lst = new List<SelectListItem>();
for (var i = 0; i < 10; i++)
{
var newdate = DateTime.Now.AddDays(i).ToString();
lst.Add(new SelectListItem() { Value = newdate, Text = newdate, Selected = false });
};
List<SelectListItem> StartDate = new List<SelectListItem>();
StartDate = lst.Select(c => new SelectListItem() { Value = c.Value, Text = c.Text, Selected = c.Selected }).ToList();
if (StartDate.Count > 0)
{
StartDate[0].Selected = true;
System.Diagnostics.Debug.WriteLine("Start Date: " + StartDate[0].Text);
}
ViewBag.ListStartDate = StartDate;
//For EndDate, set "Select" for the last Entry
List<SelectListItem> EndDate = new List<SelectListItem>();
EndDate = lst.Select(c => new SelectListItem() { Value = c.Value, Text = c.Text, Selected = c.Selected }).ToList(); //lst is the default list without any select set to true
if (EndDate.Count > 0)
{
EndDate[EndDate.Count - 1].Selected = true;
System.Diagnostics.Debug.WriteLine("End Date: " + EndDate[EndDate.Count - 1].Text);
}
System.Diagnostics.Debug.WriteLine("[Finished End Info]");
ViewBag.ListEndDate = EndDate;
Besides, you could also Create a DateModel, and use it to store the DropDownList select items, code as below:
public class DateModel
{
public string Value { get; set; }
public string Text { get; set; }
public bool IsSelected { get; set; }
}
Controller:
public IActionResult Index()
{
List<DateModel> lst = new List<DateModel>();
for(var i =0;i<10; i++)
{
var newdate = DateTime.Now.AddDays(i).ToString();
lst.Add(new DateModel() { Value = newdate, Text = newdate, IsSelected = false });
};
List<SelectListItem> StartDate = new List<SelectListItem>();
StartDate = lst.Select(c=> new SelectListItem() { Value = c.Value, Text = c.Text, Selected = c.IsSelected }).ToList();
if (StartDate.Count > 0)
{
StartDate[0].Selected = true;
System.Diagnostics.Debug.WriteLine("Start Date: " + StartDate[0].Text);
}
ViewBag.ListStartDate = StartDate;
//For EndDate, set "Select" for the last Entry
List<SelectListItem> EndDate = new List<SelectListItem>();
EndDate = lst.Select(c => new SelectListItem() { Value = c.Value, Text = c.Text, Selected = c.IsSelected }).ToList(); //lst is the default list without any select set to true
if (EndDate.Count > 0)
{
EndDate[EndDate.Count - 1].Selected = true;
System.Diagnostics.Debug.WriteLine("End Date: " + EndDate[EndDate.Count - 1].Text);
}
System.Diagnostics.Debug.WriteLine("[Finished End Info]");
ViewBag.ListEndDate = EndDate;
return View();
}
Then, the result as below:

Related

How to group DataGridView?

My current DataGridView looks like this:
I'd like to achieve that each (column) "Fachanwendung" is grouping the data by displaying it as a Header. I've tried it with the DataGridViewGrouper like here: https://10tec.com/articles/datagridview-grouping-two-recipes.aspx
https://www.codeproject.com/Tips/995958/DataGridViewGrouper
Unfortunately, my DataSource and DataMembers are either null or "". Therefore I can't call it like this:
DataGridViewGrouper grouper = new DataGridViewGrouper(dataGridView);
grouper.SetGroupOn("Fachanwendung");
//grouper.SetGroupOn(this.dataGridView.Columns["fachanwendung"]);
Is there any other way to display (at least a text) over a specific row?
I created a DataTable which you can use as the DatSource of the DGV. See code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication98
{
class Program
{
static void Main(string[] args)
{
List<Element> elements = new List<Element>() {
new Element() { Fachanwendung = "archiMap", Elementtyp = "Herstellerproduktversion", Elementname = "Java SE JRE 8", Date = DateTime.Parse("1/1/2017"), Quantity = 10},
new Element() { Fachanwendung = "archiMap", Elementtyp = "Herstellerproduktversion", Elementname = "Microsoft Window Server 2012 Standard", Date = DateTime.Parse("3/1/2017"), Quantity = 12},
new Element() { Fachanwendung = "Event Management System", Elementtyp = "Herstellerproduktversion", Elementname = "Apache Toimcat 8.0", Date = DateTime.Parse("6/1/2018"), Quantity = 5},
new Element() { Fachanwendung = "Event Management System", Elementtyp = "Herstellerproduktversion", Elementname = "Oracle Java JDK 7", Date = DateTime.Parse("12/1/2018"), Quantity = 5},
new Element() { Fachanwendung = "Event Management System", Elementtyp = "Herstellerproduktversion", Elementname = "Oracle Java JDK 8", Date = DateTime.Parse("1/1/2019"), Quantity = 5}
};
Dictionary<string, List<Element>> dict = elements.GroupBy(x => x.Fachanwendung, y => y)
.ToDictionary(x => x.Key, y => y.ToList());
DataTable dt = new DataTable();
dt.Columns.Add("Fachanwendung", typeof(string));
dt.Columns.Add("Elementtyp", typeof(string));
dt.Columns.Add("Elementname", typeof(string));
//add quarters
DateTime minDate = dict.SelectMany(x => x.Value.Select(y => y.Date)).Min(x => x.Date);
DateTime maxDate = dict.SelectMany(x => x.Value.Select(y => y.Date)).Max(x => x.Date);
DateTime startQuarter = new DateTime(minDate.Year, ((minDate.Month - 1) % 3) + 1, 1);
DateTime endQuarter = new DateTime(maxDate.Year, ((maxDate.Month - 1) % 3) + 1, 1);
for (DateTime date = startQuarter; date <= endQuarter; date = date.AddMonths(3))
{
dt.Columns.Add(date.Year.ToString() + " Q" + (((date.Month - 1)/ 3) + 1).ToString(), typeof(int));
}
foreach (KeyValuePair<string, List<Element>> rows in dict)
{
var groups = dict[rows.Key].GroupBy(x => new { Elementtyp = x.Elementtyp, Elementname = x.Elementname, Date = new DateTime(x.Date.Year, ((x.Date.Month - 1) % 3) + 1, 1) }).ToList();
foreach (var group in groups)
{
DataRow newRow = dt.Rows.Add();
newRow["Fachanwendung"] = rows.Key;
newRow["Elementtyp"] = group.Key.Elementtyp;
newRow["Elementname"] = group.Key.Elementname;
string quarter = group.Key.Date.Year.ToString() + " Q" + (((group.Key.Date.Month - 1) / 3) + 1).ToString();
int total = group.Sum(x => x.Quantity);
newRow[quarter] = total;
}
}
}
}
public class Element
{
public string Fachanwendung { get; set; }
public string Elementtyp { get; set; }
public string Elementname { get; set; }
public DateTime Date { get; set; }
public int Quantity { get; set; }
}
}
I got your requirement now basically you want to have a block for each group in the data grid view. This can be resolved using Nested grid view. Here is very good link which you can use https://www.codeproject.com/Articles/848637/Nested-DataGridView-in-windows-forms-csharp
Also if you don't want expand collapse functionality you can easily remove that. Let me know if you need help with that.

GROUPBY and SUM on List items using LINQ

I have a List of type DailySummary
public class DailySummary
{
public string AffiliateID { get; set; }
public string TotalCalls { get; set; }
public string Date{ get; set; }
}
with following sample data:
List<DailySummary> DealerTFNDatesTable = new List<DailySummary>();
DealerTFNDatesTable.Add(new DailySummary() { AffiliateID="0", Date = "12/12/2016", TotalCalls = "10"});
DealerTFNDatesTable.Add(new DailySummary() { AffiliateID="0", Date = "12/13/2016", TotalCalls = "74"});
DealerTFNDatesTable.Add(new DailySummary() { AffiliateID="1", Date = "12/22/2016", TotalCalls = "63"});
DealerTFNDatesTable.Add(new DailySummary() { AffiliateID="0", Date = "12/12/2016", TotalCalls = "58"});
Now I want to retrieve Date and TotalCalls grouped by AffiliateID and assign in another list.
for(int i =0; i < DealerTFNDatesTable.Count; i++)
{
List<NewList> newList = new List<NewList>();
newList.Date = //Assign Dintinct dates WHERE AffiliateId = 0
newList.AffiliateID = //AffiliateID=0
newList.TotalCalls= //TotalCalls SUM GROUPBY DATE and AffiliateID = 0
//For Date '12/12/2016' it will be 68, For '12/13/2016' it will be 74 and so on
}
I'm sorry, I'm new to LINQ. Can someone help me or share resources where I can get a hint to achieve this?
This should work for grouping by AffilateID and Date and then getting the sum (though it's weird to store a number as a string for something like this, but whatever floats your boat).
var results = DealerTFNDatesTable
.GroupBy(x => new { x.AffiliateID, x.Date })
.Select(x => new DailySummary {
AffiliateID = x.First().AffiliateID,
Date = x.First().Date,
TotalCalls = x.Sum(y => Convert.ToInt32(y.TotalCalls)).ToString()
});
If you now look at the result, for example with this code, you get exactly the values you wanted:
foreach (var x in results) {
Console.WriteLine($"id = {x.AffiliateID}, date = {x.Date}, totalCalls = {x.TotalCalls}");
}
> id = 0, date = 12/12/2016, totalCalls = 68
> id = 0, date = 12/13/2016, totalCalls = 74
> id = 1, date = 12/22/2016, totalCalls = 63
First off,
Since DealerTFNDatesTable is a variable, you should use camel case. Thus it is dealerTFNDatesTable
Then to complete #andy his answer, as you also want to do a select. You can select it as follows:
var newVariable = from item in dealerTFNDatesTable
group item by new
{
item.Date,
item.AffiliateID,
}
into g
select new
{
Date = g.Key.Date,
Id = g.Key.AffiliateID,
Total = g.Sum(a => a.TotalCalls)
};
This will give you an IEnumerable, of which you can put the relevant parts in a list by doing var otherList = new List<object>(newVariable
.Where(a => a.Total > 0)); or simply add .ToList() after the select if you want the collection as-is.
Note that this is simply another notation than LINQ, the result is the same.
var results = DealerTFNDatesTable.GroupBy(T => new { T.AffiliateID })
Link

Checking multiple DateTime of Interferences

I got a list of DateTime which contains StartDate and EndDate,
User Should Select one or more TimeSpans from this list.
They are also have a structure class Named Courses.
How can I check if any overlaps is Happening or not
For example I got this
Start Date End Date
#1 7/20/2016 7/27/2016 Selected
#2 6/18/2016 7/25/2016 Selected
#3 7/20/2016 7/27/2016
#4 6/5/2016 6/10/2016
In this Example user has selected 2 dates that contains overlaps .
I want to warn the user with a message box or some Using C#.
Any opinion
Thanks
Ok, first created a class TimePeriod like this:
public class TimePeriod
{
public int Id;
public DateTime FromDate
{
get; set;
}
public DateTime ToDate
{
get; set;
}
public static DateTime Parse(string date)
{
var dt = DateTime.Parse(date,
CultureInfo.CreateSpecificCulture("en-US"), DateTimeStyles.RoundtripKind);
return dt;
}
}
Then created a List with items of this class:
List<TimePeriod> list = new List<TimePeriod>();
Then added your examples of Dates (added all of them, for your need just add selected one's):
list.Add(new TimePeriod() { Id = 1, FromDate = TimePeriod.Parse("7/20/2016"), ToDate = TimePeriod.Parse("7/27/2016") });
list.Add(new TimePeriod() { Id = 2, FromDate = TimePeriod.Parse("6/18/2016"), ToDate = TimePeriod.Parse("7/25/2016") });
list.Add(new TimePeriod() { Id = 3, FromDate = TimePeriod.Parse("7/20/2016"), ToDate = TimePeriod.Parse("7/27/2016") });
list.Add(new TimePeriod() { Id = 4, FromDate = TimePeriod.Parse("6/5/2016"), ToDate = TimePeriod.Parse("6/10/2016") });
And last check with LINQ for overlapping:
var overlaps = from current in list
from compare in list
where
(
(compare.FromDate > current.FromDate &&
compare.FromDate < current.ToDate) ||
(compare.ToDate > current.FromDate &&
compare.ToDate < current.ToDate)
)
select new
{
Id1 = current.Id,
Id2 = compare.Id,
};
The result will be in this case 1/2 & 2/1 and 2/3 & 3/2. In your case it will be 1/2 & 2/1.
There is a very good library for working with time periods and their intersection on nuget.
Time Period Library
There is also an article on code project for it.
Time Period Library for .NET
You need to store which dates have been selected and if they occur in multiple selections right?
Store startedate and enddate of each selected timespan to a Tuple selectedTimeSpans
then:
List<int> useddays =new List<int>();
foreach (Tuple<DateTime, DateTime> selected in selectedTimeSpans)
{
DateTime start = selected.Value1;
DateTime end = selected.Value2;
DateTime current = start;
while(current <=end)
{
if(useddays.Contains((current-DateTime.MinValue).TotalDays)
MessageBox. Show("Already used!");
else
useddays.Add((current-DateTime.MinValue).TotalDays);
current.AddDays(1);
}
}
Thanks To all #c0d3b34n and #ThomasVoß ,
Also to this article https://stackoverflow.com/a/325964/3970128
This is All I Have Done
Ok, first created a class TimePeriod like this:
public class TimePeriod
{
public int Id;
public DateTime FromDate
{
get; set;
}
public DateTime ToDate
{
get; set;
}
public static DateTime Parse(string date)
{
var dt = DateTime.Parse(date,
CultureInfo.CreateSpecificCulture("en-US"), DateTimeStyles.RoundtripKind);
return dt;
}
}
Then created a List with items of this class:
List<TimePeriod> list = new List<TimePeriod>();
Then added your examples of Dates (added all of them, for your need just add selected one's):
list.Add(new TimePeriod() { Id = 1, FromDate = TimePeriod.Parse("7/20/2016"), ToDate = TimePeriod.Parse("7/27/2016") });
list.Add(new TimePeriod() { Id = 2, FromDate = TimePeriod.Parse("6/18/2016"), ToDate = TimePeriod.Parse("7/25/2016") });
list.Add(new TimePeriod() { Id = 3, FromDate = TimePeriod.Parse("7/20/2016"), ToDate = TimePeriod.Parse("7/27/2016") });
list.Add(new TimePeriod() { Id = 4, FromDate = TimePeriod.Parse("6/5/2016"), ToDate = TimePeriod.Parse("6/10/2016") });
Then
foreach (var variable in list)
{
foreach (var VARIABLE in list)
{
if (variable.Id == VARIABLE.Id)
{
continue;
}
if ((variable.FromDate <= VARIABLE.ToDate) && (variable.ToDate >= VARIABLE.FromDate))
{
Console.WriteLine("Problem Hapendes!! {0} <= {1} , {2} >= {3}", variable.FromDate.ToString(), VARIABLE.ToDate.ToString(), VARIABLE.ToDate.ToString(), VARIABLE.FromDate.ToString());
}
}
}

Html.DropdownList(allsundaysinmonth) set default to sunday just past

I have no idea how to work this out but my drop down list code looks as follows:
in the action:
DateTime[] allSundaysInMonth = GetDatesOfSundays(System.DateTime.Now);
DateTime[] allSundaysInLastMonth = GetDatesOfSundays(System.DateTime.Now.AddDays(-30));
List<SelectListItem> listOfSundays = new List<SelectListItem>();
foreach (DateTime dt in allSundaysInThisMonth)
{
listOfSundays.Add(new SelectListItem
{
Text = dt.Name,
Value = dt.Id.ToString(),
Selected = dt.CompanyId == Id
});
return listOfSundays;
}
I need to take the last two sundays af last month and all sundays of this month, but not future sundays, and build a list with all these sundays.
This is something i did while on a past project
public List<SelectListItem> CompanySelectList(List<Company> companyList, int selectedId = 0)
{
List<SelectListItem> listToReturn = new List<SelectListItem>();
foreach (Company c in companyList)
{
listToReturn.Add(new SelectListItem
{
Text = c.CompanyName,
Value = c.CompanyId.ToString(),
Selected = c.CompanyId == selectedId
});
}
return listToReturn;
}
just modify your T so it will return what you need.
You could look at the current date and start looping down, if the date then returned is a sunday set this value to be selected.

How do I make this NHibernate QueryOver query return rows for empty groups

The following NHibernate QueryOver query is counting the number of applications for each month, within a given date range.
However, I don't get any results for months that don't have any applications in them but I want to actually have Count = 0 returned for those months.
So how would I change the query to return a row as well for months that don't have any applications in them?
DateTimeOffset endDate = DateTimeOffset.Now;
DateTimeOffset startDate = endDate.AddMonths(-12);
var result = Session.QueryOver<Application>()
.WhereRestrictionOn(c => c.SubmissionDate).IsBetween(startDate).And(endDate)
.SelectList(list => list
.Select(Projections.SqlGroupProjection(
"YEAR(SubmissionDate) As [Year]",
"YEAR(SubmissionDate)",
new[] { "YEAR" },
new IType[] { NHibernateUtil.Int32 }))
.Select(Projections.SqlGroupProjection(
"MONTH(SubmissionDate) As [Month]",
"MONTH(SubmissionDate)",
new[] { "MONTH" },
new IType[] { NHibernateUtil.Int32 }))
.SelectCount(x => x.Id))
.OrderBy(Projections.SqlFunction(
"YEAR",
NHibernateUtil.Int32,
Projections.Property<Application>(item => item.SubmissionDate))).Asc
.ThenBy(Projections.SqlFunction(
"MONTH",
NHibernateUtil.Int32,
Projections.Property<Application>(item => item.SubmissionDate))).Asc
.List<object[]>()
.Select(n => new
{
Year = n[0],
Month = n[1],
Count = (int)n[2]
}));
Update: taking your idea with DateTime.AddMonths() it gets even shorter
DateTime lastMonth = startdate;
var unionresults = result.SelectMany(r =>
{
var actualDate = new DateTime(r.Year, r.Month, 1);
var results = Enumerable.Repeat(1, Months)
.Select(i => lastMonth.AddMonths(i))
.TakeWhile(date => date < actualDate)
.Select(date => new { Year = date.Year, Month = date.Month, Count = 0 })
.Concat(new[] { r });
lastMonth = actualDate;
return results;
});
Original:
i think you have to add that data after the query. here an example using linq to fill in missing months
var result = <query>;
int lastMonth = 1;
var unionresults = result.SelectMany(r =>
{
var results = new[] { r }.AsEnumerable();
if (lastMonth > r.Month)
{
results = Enumerable.Range(lastMonth, 12 - lastMonth).Select(month => new { Year = r.Year, Month = month, Count = 0 })
.Concat(Enumerable.Range(1, r.Month).Select(month => new { Year = r.Year, Month = month, Count = 0 }))
.Concat(results);
}
else if (lastMonth < r.Month)
{
results = Enumerable.Range(lastMonth, r.Month - lastMonth)
.Select(month => new { Year = r.Year, Month = month, Count = 0 })
.Concat(results);
}
lastMonth = r.Month + 1;
if (lastMonth > 12)
{
lastMonth = 1;
}
return results;
});
It cannot be done with a few simple changes. The SQL query that is generated by your QueryOver() cannot count what does not exist in the first place.
You could probably do it with a UNION or a JOIN using a virtual/temporary table (depending on the DBMS) but that would make the query overly complicated.
I suggest adding a loop after your query that iterates through the list, copies the elements to a new list and adds any non-existing months to that new list. Something like this:
class YearMonthCount
{
public int Year { get; set; }
public int Month { get; set; }
public int Count { get; set; }
}
// Start and End dates
DateTime startDate = new DateTime(2011, 9, 1);
DateTime endDate = new DateTime(2012, 6, 1);
// this would be a sample of the QueryOver() result
List<YearMonthCount> result = new List<YearMonthCount>();
result.Add(new YearMonthCount { Year = 2011, Month = 10, Count = 2 });
result.Add(new YearMonthCount { Year = 2011, Month = 11, Count = 3 });
result.Add(new YearMonthCount { Year = 2012, Month = 1, Count = 4 });
result.Add(new YearMonthCount { Year = 2012, Month = 2, Count = 1 });
result.Add(new YearMonthCount { Year = 2012, Month = 4, Count = 1 });
result.Add(new YearMonthCount { Year = 2012, Month = 5, Count = 1 });
int i = 0;
List<YearMonthCount> result2 = new List<YearMonthCount>();
// iterate through result list, add any missing entry
while (startDate <= endDate)
{
bool addNewEntry = true;
// check to avoid OutOfBoundsException
if (i < result.Count)
{
DateTime listDate = new DateTime(result[i].Year, result[i].Month, 1);
if (startDate == listDate)
{
// entry is in the QueryOver result -> add this
result2.Add(result[i]);
i++;
addNewEntry = false;
}
}
if (addNewEntry)
{
// entry is not in the QueryOver result -> add a new entry
result2.Add(new YearMonthCount {
Year = startDate.Year, Month = startDate.Month, Count = 0 });
}
startDate = startDate.AddMonths(1);
}
This could probably be done more elegantly but it gets the job done.
Thanks to all the answers, this is how I ended up doing it:
DateTime endDate = DateTime.Now;
DateTime startDate = endDate.AddMonths(-Months);
var result = Session.QueryOver<Application>()
.WhereRestrictionOn(c => c.SubmissionDate).IsBetween(startDate).And(endDate)
.SelectList(list => list
.Select(Projections.SqlGroupProjection(
"YEAR(SubmissionDate) As [Year]",
"YEAR(SubmissionDate)",
new[] { "YEAR" },
new IType[] { NHibernateUtil.Int32 }))
.Select(Projections.SqlGroupProjection(
"MONTH(SubmissionDate) As [Month]",
"MONTH(SubmissionDate)",
new[] { "MONTH" },
new IType[] { NHibernateUtil.Int32 }))
.SelectCount(x => x.Id))
.List<object[]>()
.Select(n => new
{
Year = (int)n[0],
Month = (int)n[1],
Count = (int)n[2]
}).ToList();
var finalResult = result
.Union(
Enumerable.Range(0, Months - 1).Select(n => new
{
Year = startDate.AddMonths(n).Year,
Month = startDate.AddMonths(n).Month,
Count = 0
})
.Where(n => !result.Any(r => r.Year == n.Year && r.Month == n.Month)))
.OrderBy(n => n.Year).ThenBy(n => n.Month);

Categories