I am going to create print page in wpf with *.rdlc.
For this , i create a class(following is this codes).
I bind the class to report but when i run the program , following message occurs :
A data source instant has not been supplied for data source 'dataset1'
class rpt_insurance
{
private string _insurance;
private int _count_print;
private int _sum_tariff;
private int _lot_org;
public string insurance
{
get { return _insurance; }
set { _insurance = value; }
}
public int count_print
{
get { return _count_print; }
set { _count_print = value; }
}
public int sum_tariff
{
get { return _sum_tariff; }
set { _sum_tariff = value; }
}
public int lot_org
{
get { return _lot_org; }
set { _lot_org = value; }
}
public DataTable report_insurance(string from_date,string to_date)
{
using (doctorEntities de = new doctorEntities())
{
var print = (from Table_infobase_print tip in de.Table_infobase_print
where tip.Print_date.CompareTo(from_date) > 0 && tip.Print_date.CompareTo(to_date) < 0
select tip).ToList();
var insurance = (from Table_insurance_org tio in de.Table_insurance_org
select tio).ToList();
List<rpt_insurance> lri = new List<rpt_insurance>();
foreach (var insurance_row in insurance)
{
rpt_insurance ri = new rpt_insurance();
int number = 0;
foreach (var print_row in print)
{
if(print_row.insurance_org==insurance_row.org_name)
{
number++;
ri.insurance = print_row.insurance_org;
ri.count_print = number;
ri.sum_tariff = ri.sum_tariff + print_row.sum_tariff;
ri.lot_org=lot_org+(print_row.sum_tariff-print_row.sum_lot_patient);
}
}
if (ri.insurance != null)
{
lri.Add(ri);
}
}
DataTable dt = new DataTable();
dt = new DataTable();
dt.Columns.Add("cinsurance");
dt.Columns.Add("ccount_print");
dt.Columns.Add("csum_tariff");
dt.Columns.Add("clot_org");
for (int i = 0; i < lri.Count; i++)
{
DataRow dr = dt.NewRow();
dr["cinsurance"] = lri[i].insurance;
dr["ccount_print"] = lri[i].count_print;
dr["csum_tariff"] = lri[i].sum_tariff;
dr["clot_org"] = lri[i].lot_org;
dt.Rows.Add(dr);
}
return dt;
}
}
}
You need to supply the dataset to your report. Something like:
viewer.LocalReport.DataSources.Add(new ReportDataSource("dataset1", dataTable));
Edit: based on your comment
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var dataTable = report_insurance(fromDate, toDate);
viewer_insurance.LocalReport.ReportPath = "E:\\desktop\\Doctor\\Project\\Doctor\\Doctor\\rinsurance.rdlc";
viewer_insurance.LocalReport.DataSources.Add(new ReportDataSource("dataset1", dataTable);
viewer_insurance.RefreshReport();
}
You really can't get around the need to call your data retrieval method AND send that data through to the report.
Related
I have created a small form and a user control , but I don't know how to pass data from one side of the database to the other user control , followed some tutorials on the net and I used the (get;set) pair like that. this:
IN Main form
string query = #"select t.Ma_Nvu,t.Ten_Nvu,t.Time_Start,t.Time_End,d.Noi_dung from ToDoList_ListNvu t
left join ToDoList_NoiDungNvu d on t.Ma_Nvu = d.Ma_Nvu
where t.Status like N'Chưa hoàn thành'";
dt = (new Data()).executeQuery(query);
if (dt.Rows.Count == 0)
{
MessageBox.Show("Bạn cần tạo nhiệm vụ trước để vào !", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
ProcessToDoList tdl = new ProcessToDoList();
BunifuTransition trans = new BunifuTransition();
this.PageToDoList.Controls.Add(tdl);
tdl.Location = new Point(0, 0);
tdl.Size = new Size(0, 567);
if (tdl.Width == 0)
{
tdl.Width = 1014;
trans.ShowSync(tdl, false, Bunifu.UI.WinForms.BunifuAnimatorNS.Animation.HorizBlind);
tdl.BringToFront();
}
foreach (DataRow dr in dt.Rows)
{
DataList data = new DataList();
data.Name = dr["Ten_Nvu"].ToString();
data.Time_Start = dr["Time_Start"].ToString();
data.Time_End = dr["Time_End"].ToString();
data.Noi_Dung = dr["Noi_dung"].ToString();
dtaAdd.Add(data);
}
int i = 0;
while (i < dt.Rows.Count)
{
tdl.Name_Nvu = dtaAdd[i].Name;
tdl.Noi_dung = dtaAdd[i].Noi_Dung;
tdl.Time_Start = dtaAdd[i].Time_Start;
tdl.Time_End = dtaAdd[i].Time_End;
if (tdl.CheckOut()==true)
{
i++;
}
}
In UserControl
public string Name_Nvu
{
get { return _name; }
set { _name = value; }
}
public string Noi_dung
{
get {return _noidung ; }
set {_noidung = value; }
}
public string Time_Start
{
get { return _timestart; }
set { _timestart = value; }
}
public string Time_End
{
get { return _timeend; }
set { _timeend = value; }
}
But it doesn't work. I don't know where the error is, so I want to ask everyone how can I pass data from form to user control.
I'm not sure what error message ur getting, but passing value from your form to your UC could be done this way.
In your User Control:
private string _name;
[Category("Custom Props")]
public string custom_name
{
get { return _name; }
set { _name = value; }
}
Then in your form, you can assign value to the _name string in the user control by doing something like this:
myUC test = new myUC(); //Your user control
test.custom_name = dtaAdd[i].Name;
panel1.Controls.Add(test);
Good day,
I try that when I connect two documents, the numbered lists are reset. As in the example below.
I use the Xceed.Words.NET DocX libary.
In this Sample, the Template is :
Test Header
List:
1) <-This should be one
And the Result is:
Test Header
List:
1) <-This should be one
Test Header
List:
2) <-This should be one
Test Header
List:
3) <-This should be one
With the following code I am able to create the lists with similar formatting, but the formatting does not match 100%. Does anyone have any idea which way to try otherwise?
Note the number of existing paragraphs and call the function to reset the list after inserting the document.
/// <summary>
/// Insert complete WordFile
/// </summary>
/// <param name="wordFile"></param>
public void InsertWordTemplate(IWordFile wordFile, bool InsertPageBreak)
{
if (wordFile != null && wordFile.IsFileOk)
{
int pargraphCount = Document.Paragraphs.Count - 1;
// NotNeeded for this Problem wordFile.RemoveStyles();
// NotNeeded for this Problem RemoveHeaderAndFooter(wordFile);
Document.InsertDocument(wordFile.Document);
// NotNeeded for this Problem ReplaceSectionBreak(InsertPageBreak, pargraphCount);
ResetNumberedList(pargraphCount);
logger.Info("Word file inserted: " + wordFile.File.FullName);
}
else
{
logger.Warn("Word file is not okay - will not be inserted: " + wordFile?.File?.FullName);
}
}
In the Word document, three different names are used in a list, only from the 4th level is worked with a level. For other Word templates they are called different.
private void ResetNumberedList(int pargraphCount)
{
string styleName1 = "ListNumbers";
string styleName2 = "PIgeordneteListe2Ebene";
string styleName3 = "PIgeordneteListe3Ebene";
NumberedListReset numberedListReset = new NumberedListReset(Document, styleName1, styleName2, styleName3);
bool OnlyFirstFoundList = true;
numberedListReset.Reset(pargraphCount, OnlyFirstFoundList);
}
Below is the helper class with which I try to reset the numbering. I do this by myself
I notice the formatting of the individual list items, create new lists, fill them with the old values, set the styles correctly again and then insert everything into old place.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Xceed.Document.NET;
using Xceed.Words.NET;
namespace PIB.Report.DataWriter.WordExport
{
public class NumberedListReset
{
private readonly DocX _Document;
private readonly string _StyleName1;
private readonly string _StyleName2;
private readonly string _StyleName3;
public NumberedListReset(DocX Document, string StyleName1, string StyleName2, string StyleName3)
{
_Document = Document;
_StyleName1 = StyleName1;
_StyleName2 = StyleName2;
_StyleName3 = StyleName3;
}
public void Reset(int StartParagraphNumber, bool OnlyFirstFinding)
{
for (int i = StartParagraphNumber; i < _Document.Paragraphs.Count; i++)
{
var paragraph = _Document.Paragraphs[i];
if (paragraph.IsListItem == true && paragraph.ListItemType == ListItemType.Numbered && paragraph.StyleName == _StyleName1)
{
//int? numId = GetNumId(paragraph);
//if (numId != -1)
//{
//}
ResetFoundList(ref i);
if (OnlyFirstFinding == true)
{
break;
}
}
}
}
private void ResetFoundList(ref int ParagraphCounter)
{
List<ParagraphMemorize> ParagraphMemorizes = CreateMemorizeListItems(ParagraphCounter);
if (ParagraphMemorizes.Count != 0)
{
RemoveOldParagraphsFromDocument(ParagraphMemorizes);
List numberedList = CreateNewDocumentList();
FillDocumentList(ParagraphMemorizes, numberedList);
List<Paragraph> actualListData = numberedList.Items;
ResetSyleNames(ParagraphMemorizes, actualListData);
InsertNewParagraphsToDocument(ParagraphCounter, actualListData);
ParagraphCounter += ParagraphMemorizes.Count;
}
}
private List<ParagraphMemorize> CreateMemorizeListItems(int ParagraphCounter)
{
List<ParagraphMemorize> ParagraphMemorizes = new List<ParagraphMemorize>();
for (int ii = ParagraphCounter; ii < _Document.Paragraphs.Count; ii++)
{
var paragraph = _Document.Paragraphs[ii];
if (!NameIsKnown(paragraph.StyleName))
{
break;
}
ParagraphMemorize paragraphMemorize = new ParagraphMemorize(paragraph);
paragraphMemorize.ListLevel = GetListLevel(paragraph);
ParagraphMemorizes.Add(paragraphMemorize);
}
return ParagraphMemorizes;
}
private void RemoveOldParagraphsFromDocument(List<ParagraphMemorize> ParagraphMemorizes)
{
ParagraphMemorizes.ForEach(m => _Document.RemoveParagraph(m.Paragraph));
}
private List CreateNewDocumentList()
{
return _Document.AddList(startNumber: 1);
}
private void FillDocumentList(List<ParagraphMemorize> ParagraphMemorizes, List numberedList)
{
for (var ii = 0; ii < ParagraphMemorizes.Count; ii++)
{
//numberedList.AddItem(ParagraphMemorizes[ii].Paragraph); //Raised an Error
ParagraphMemorize paragraphMemorize = ParagraphMemorizes[ii];
int listLevel = GetListLevel(paragraphMemorize);
_Document.AddListItem(numberedList, paragraphMemorize.Text, listLevel);
}
}
private static void ResetSyleNames(List<ParagraphMemorize> ParagraphMemorizes, List<Paragraph> actualListData)
{
for (int ii = 0; ii < actualListData.Count; ii++)
{
actualListData[ii].StyleName = ParagraphMemorizes[ii].StyleName;
}
}
private void InsertNewParagraphsToDocument(int i, List<Paragraph> actualListData)
{
Paragraph paragraph = _Document.Paragraphs[i];
for (int ii = 0; ii < actualListData.Count; ii++)
{
paragraph.InsertParagraphBeforeSelf(actualListData[ii]);
}
}
private bool NameIsKnown(string Name)
{
return Name == _StyleName1 | Name == _StyleName2 | Name == _StyleName3;
}
private int GetListLevel(ParagraphMemorize paragraphMemorize)
{
if (paragraphMemorize.StyleName == _StyleName1)
{
return 0;
}
else if (paragraphMemorize.StyleName == _StyleName2)
{
return 1;
}
else if (paragraphMemorize.StyleName == _StyleName3)
{
return (int)paragraphMemorize.ListLevel;
}
else
{
return 0;
}
}
private int? GetNumId(Paragraph paragraph)
{
var numIds = paragraph.ParagraphNumberProperties.Descendants().Where(e => e.Name.LocalName.Equals("numId"));
foreach (var numId in numIds)
{
XNamespace nsW = Namespace.WordNamespace;
var values = numId.Attributes(XName.Get("val", nsW.ToString()));
foreach (var value in values)
{
int resultId = 0;
int.TryParse(value.Value, out resultId);
return resultId;
}
}
return null;
}
private int? GetListLevel(Paragraph paragraph)
{
var numIds = paragraph.ParagraphNumberProperties.Descendants().Where(e => e.Name.LocalName.Equals("ilvl"));
foreach (var numId in numIds)
{
XNamespace nsW = Namespace.WordNamespace;
var values = numId.Attributes(XName.Get("val", nsW.ToString()));
foreach (var value in values)
{
int resultId = 0;
int.TryParse(value.Value, out resultId);
return resultId;
}
}
return null;
}
private class ParagraphMemorize
{
public Paragraph Paragraph { get; set; }
public string Text { get; set; }
public string StyleName { get; set; }
public int? ListLevel { get; set; }
public ParagraphMemorize(Paragraph Paragraph)
{
this.Paragraph = Paragraph;
this.Text = Paragraph.Text;
this.StyleName = Paragraph.StyleName;
}
}
}
}
I have a controller that calls an api to get a list of Positions and Employees . First it puts the api results into a model class - IDMSElements (1). Then the controller takes the IDMSElements object and converts it to a PositionSlots object (2). Then the PositionSlots object needs to be updated with additional data from a database (3). So in simplified version of my controller I have:
(1) IDMSElements elements = getslots.CopyDocToElements(doc);
(2) PositionSlots myslots = (PositionSlots)elements;
(3) myslots.UpdateDetails(db);
I am concerned about the myslots.UpdateDetails(db) because additional code in the controller depends on UpdateDetails having been run. I would like the UpdateDetails to be run by default when creating the PositionSlots object. But I think multiple database calls in a constructor probably should not be done. How can I make it so the UpdateDetails is automatically invoked after the PositionSlots object is instantiated?
Thank you very much!
Controller:
[Authorize]
public class PSListController : Controller
{
private static readonly log4net.ILog _logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private PositionControlContext db = new PositionControlContext();
private GetPositionSlots getslots = new GetPositionSlots();
...
public async Task<ActionResult> ByCostCenter(int costCenter)
{
string ssapiuri = getslots.BuildAPIuri($"/current/?UDAKunit={costCenter.ToString()}");
_logger.Debug($"{ssapiuri.ToString()}");
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
HttpResponseMessage result = await getslots.GetDataFromIDMSapi(ssapiuri);
stopWatch.Stop();
_logger.Debug($"Response received. Milliseconds elapsed: {stopWatch.Elapsed.TotalMilliseconds.ToString()}");
if (result.StatusCode != HttpStatusCode.OK)
{
_logger.Debug("Error retrieving data from API. Milliseconds elapsed: " + stopWatch.Elapsed.TotalMilliseconds.ToString());
throw new HttpException(404, "NotFound");
}
stopWatch.Restart();
XDocument doc = XDocument.Load(result.Content.ReadAsStreamAsync().Result);
stopWatch.Stop();
_logger.Debug($"API result loaded into XDocument. Milliseconds elapsed: {stopWatch.Elapsed.TotalMilliseconds.ToString()}\n");
_logger.Debug(doc.ToString());
IDMSElements elements = getslots.CopyDocToElements(doc);
XMLDocStats docstats = new XMLDocStats(elements);
_logger.Debug(docstats.ToString());
PositionSlots myslots = (PositionSlots)elements;
myslots.UpdateDetails(db);
//because this is dependent upon UpdatePositionSlotId having been run
//need to find a way to force UpdateDetails to run other than calling from Controller??
var mainPositionSlots = myslots.PositionsCurrentAndActive;
var budget = db.Database.SqlQuery<Budget>("GetBudgetForCostCenter #costCenter = {0}", costCenter);
List<Budget> budgetRows = budget.ToList();
JobClassGroups jobClassGroups = new JobClassGroups(mainPositionSlots, budgetRows);
Department dept = db.Departments.AsNoTracking().Where(d => d.CostCenter == costCenter).SingleOrDefault();
var model = new ByCostCenter_vm(dept, myslots, jobClassGroups);
ViewBag.stats = docstats.ToString();
return View("ByCostCenter", model);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
IDMSElements Class:
public class IDMSElements
{
//properties
public ICollection<IDMSElementData> Elements { get; set; }
//constructors
public IDMSElements() { }
public IDMSElements(ICollection<IDMSElementData> elList)
{
Elements = elList;
}
//methods
public static explicit operator PositionSlots(IDMSElements obj)
{
//this is assuming we are looking at a list of elements
//that contains the "current" positions
Dictionary<string, PositionSlotDetail> positionSlots = new Dictionary<string, PositionSlotDetail>();
var sorted = from element in obj.Elements
orderby element.positionNbr
select element;
foreach (IDMSElementData el in sorted)
{
if (!positionSlots.ContainsKey(el.positionNbr))
{
PositionSlotDetail psd = new PositionSlotDetail
{
CostCenter = Int32.Parse(el.UDAKunit),
CostCenter_7Char = el.UDAKunit,
PositionNumber = el.positionNbr,
PositionSlotId = 0,
JobClassId = el.jobClassCode.Replace("-", ""),
JobClassFullDisplayCd = string.Empty,
JobTitle = string.Empty,
SalaryGradeCd = string.Empty,
FTE_percent = el.FTEpercent / 100,
EmployeeId = el.employeeID,
EmployeeName = String.Empty,
PositionEffDate = el.positionEffDate,
PositionEffDateNext = el.positionEffDateNext,
PositionBeginDate = el.positionBeginDate,
PositionEndDate = el.positionEndDate,
DirectLeaderID = string.Empty,
DirectLeaderName = string.Empty,
DirectLeaderNetID = string.Empty,
FLSAstatusCode = el.FLSAstatusCode,
FLSAstatusDesc = el.FLSAstatusDesc,
EmploymentTypeCode = el.employmentTypeCode,
EmploymentTypeDesc = el.employmentTypeDesc,
IsOverloaded = false,
};
positionSlots[el.positionNbr] = psd;
}
Assignment newAssignment = new Assignment
{
PvID = el.employeeID,
AssignBeginDate = el.assignBeginDate,
AssignEndDate = el.assignEndDate,
AssignEffDate = el.assignEffDate,
AssignEffDateNext = el.assignEffDateNext,
};
PositionSlotDetail thePSD = positionSlots[el.positionNbr];
thePSD.Assignments.Add(newAssignment);
if (thePSD.Assignments.Any(assignment => Regex.IsMatch(assignment.PvID, #"^\d+$")))
{
thePSD.Status = "FILLED";
if (thePSD.Assignments.Where(assignment => Regex.IsMatch(assignment.PvID, #"^\d+$")).Count() > 1)
{
thePSD.IsOverloaded = true;
}
}
else
{
thePSD.Status = "VACANT";
}
}
var output = new PositionSlots(positionSlots.Values.ToList());
return output;
}
...
}
PositionSlots class:
public class PositionSlots
{
//Constructor
public PositionSlots(ICollection<PositionSlotDetail> pslist)
{
Positions = pslist;
}
//properites
public ICollection<PositionSlotDetail> Positions { get; }
private bool DetailsUpdated { get; set; } = false;
public IEnumerable<PositionSlotDetail> PositionsCurrentAndActive
{
get
{
return from position in Positions
where position.PositionSlotId > 0 && position.PositionEndDate >= DateTime.Today
select position;
}
}
public IEnumerable<PositionSlotDetail> PositionsNotFoundInPositionControl
{
get
{
return from position in Positions
where position.PositionSlotId == 0
select position;
}
}
public IEnumerable<PositionSlotDetail> PositionsClosed
{
get
{
return from psd in Positions
where psd.PositionEndDate < DateTime.Today
&& psd.PositionSlotId > 0
select psd;
}
}
public decimal ActualFTETotal
{
get
{
return (from position in PositionsCurrentAndActive
from assignment in position.Assignments
where position.Assignments.Count() >= 1 && (!assignment.PvID.Equals("VACANT"))
select position.FTE_percent).Sum();
}
}
public int FilledTotal
{
get
{
return PositionsCurrentAndActive.Where(x => x.Status == "FILLED").Count();
}
}
public int VacantTotal
{
get
{
return PositionsCurrentAndActive.Where(x => x.Status == "VACANT").Count();
}
}
public int OverloadedTotal
{
get
{
return PositionsCurrentAndActive.Where(x => x.IsOverloaded).Count();
}
}
//methods
public void UpdateDetails(PositionControlContext db)
{
if (!DetailsUpdated)
{
UpdateJobClassificationInfo(db);
UpdateEmployeeName(db);
UpdatePositionSlotId(db); //if not found, PositionSlotId = 0
//UpdateIsBudgeted(db);
UpdateDirectLeader(db);
DetailsUpdated = true;
}
else
{
return;
}
}
private void UpdateJobClassificationInfo(PositionControlContext db)
{
string[] jobClassIds = (from x in Positions select x.JobClassId).Distinct().ToArray();
var JobClassList = (from jc in db.JobClassifications where jobClassIds.Contains(jc.JobClassId) select jc).ToDictionary(jc => jc.JobClassId, jc => jc, StringComparer.OrdinalIgnoreCase);
foreach (PositionSlotDetail psd in Positions)
{
if (!string.IsNullOrWhiteSpace(psd.JobClassId) && !psd.JobClassId.Equals("MISSING"))
{
JobClassification jobClassification;
if (JobClassList.TryGetValue(psd.JobClassId, out jobClassification))
{
psd.JobClassFullDisplayCd = jobClassification.JobClassFullDisplayCd;
psd.JobTitle = jobClassification.JobTitle;
psd.SalaryGradeCd = jobClassification.SalaryGradeCd;
}
else
{
psd.JobClassFullDisplayCd = ($"{psd.JobClassId} not found in view V_JobClassifications.");
psd.JobTitle = ($"{psd.JobClassId} not found in view V_JobClassifications.");
psd.SalaryGradeCd = "--";
}
}
else
{
psd.JobClassFullDisplayCd = "MISSING";
psd.JobTitle = "MISSING";
}
}
return;
}
private void UpdateEmployeeName(PositionControlContext db)
{
string[] empIdsStr = (from position in Positions
from assignment in position.Assignments
where (!assignment.PvID.Equals("VACANT"))
select assignment.PvID).Distinct().ToArray();
// Positions.SelectMany(x => x.Assignments).SelectMany(x => x.PvID).ToArray();
//string[] empIdsStr = (from x in Positions where (!x.EmployeeId.Contains("VACANT")) select x.EmployeeId).Distinct().ToArray();
//int[] empIdsInt = Array.ConvertAll(empIdsStr, int.Parse);
var EmployeeList = (from emp in db.IdAM_personLU where empIdsStr.Contains(emp.pvID) select emp).ToDictionary(emp => emp.pvID,
emp => emp.EmployeeFullName, StringComparer.OrdinalIgnoreCase);
EmployeeList["VACANT"] = "VACANT";
foreach (PositionSlotDetail psd in Positions)
{
string empName;
if (EmployeeList.TryGetValue(psd.EmployeeId, out empName))
{
psd.EmployeeName = empName;
}
else
{
psd.EmployeeName = ($"{psd.EmployeeId} not found in Employee table.");
}
foreach (Assignment emp in psd.Assignments)
{
string empName2;
if (EmployeeList.TryGetValue(emp.PvID, out empName2))
{
emp.EmpDisplayName = empName2;
}
else
{
emp.EmpDisplayName = ($"{psd.EmployeeId} not found in Employee table.");
}
}
}
return;
}
private void UpdateDirectLeader(PositionControlContext db)
{
string[] empIdsStr = (from x in Positions where (!x.EmployeeId.Contains("VACANT")) select x.EmployeeId).Distinct().ToArray();
//int[] empIdsInt = Array.ConvertAll(empIdsStr, int.Parse);
Dictionary<string, IdAM_arborLU> DirectLeader = new Dictionary<string, IdAM_arborLU>();
var EmployeeDirectLeaderList = (from emp in db.IdAM_arborLU where empIdsStr.Contains(emp.emp_pvID) select emp).ToDictionary(emp => emp.emp_pvID,
emp => emp, StringComparer.OrdinalIgnoreCase);
foreach (PositionSlotDetail psd in Positions)
{
if (psd.EmployeeId != "VACANT") //will just leave DirectLeaderId and DirectLeaderName as string.Empty
{
IdAM_arborLU supervisor;
if (EmployeeDirectLeaderList.TryGetValue(psd.EmployeeId, out supervisor))
{
psd.DirectLeaderName = supervisor.sup_name;
psd.DirectLeaderID = supervisor.sup_pvID;
psd.DirectLeaderNetID = supervisor.sup_netID;
}
else
{
psd.DirectLeaderName = ($"{psd.EmployeeId} not found in Arbor table.");
}
}
foreach (Assignment emp in psd.Assignments)
{
if (psd.EmployeeId != "VACANT")
{
IdAM_arborLU supervisor2;
if (EmployeeDirectLeaderList.TryGetValue(psd.EmployeeId, out supervisor2))
{
emp.DirectLeaderName = supervisor2.sup_name;
emp.DirectLeaderID = supervisor2.sup_pvID;
emp.DirectLeaderNetID = supervisor2.sup_netID;
}
else
{
emp.DirectLeaderName = ($"{psd.EmployeeId} not found in Arbor table.");
emp.DirectLeaderID = "--";
emp.DirectLeaderNetID = "--";
}
}
}
}
return;
}
private void UpdatePositionSlotId(PositionControlContext db)
{
string[] posnumber = (from x in Positions
select x.PositionNumber).ToArray();
var slots = (from ps1 in db.PositionSlots
where posnumber.Contains(ps1.PositionNumber)
select ps1).ToDictionary(ps => ps.PositionNumber.Trim(), ps => ps.PositionSlotId, StringComparer.OrdinalIgnoreCase);
foreach (PositionSlotDetail psd in Positions)
{
int posSlotId = 0;
if (slots.TryGetValue(psd.PositionNumber, out posSlotId))
{
psd.PositionSlotId = posSlotId;
}
}
return;
}
private void UpdateIsBudgeted(PositionControlContext db)
{
string[] posnumber = (from x in Positions
select x.PositionNumber).ToArray();
var slots = (from ps1 in db.PositionSlots
where posnumber.Contains(ps1.PositionNumber)
select ps1).ToDictionary(ps => ps.PositionNumber.Trim(), ps => ps.IsBudgeted, StringComparer.OrdinalIgnoreCase);
foreach (PositionSlotDetail psd in Positions)
{
bool isbudgeted = false;
if (slots.TryGetValue(psd.PositionNumber, out isbudgeted))
{
psd.IsBudgeted = isbudgeted;
}
}
return;
}
}
you can achieve this by writing a method:
IDMSElement.ToPositionSlot(db)
and then use it as follow:
PositionSlots myslots = elements.Select(x => x.ToPositionSlot(db))
I have a rather strange requirement for a Wpf Project I'm working on. I want to be able to build a XamDataGrid with a series of DateTime fields when the user saves the data from another grid. Currently I see the second XamDataGrid with it's fields, but upon execution of the command that saves the data, although I can see in the debugger that my second list (which is bound to the second XamDataGrid) is generated, nothing displays on this second XamDataGrid.
I'll post most of my code so that somebody might help me:
The xaml (for the second datagrid as the first one is working fine):
<igDP:XamDataGrid.FieldLayouts>
<igDP:FieldLayout>
<igDP:Field Label="ID" Name="id" Width="50"></igDP:Field>
<igDP:Field Label="Descripcion" Name="descripcion" Width="400"></igDP:Field>
<igDP:UnboundField Label="Fechas de Pago" Name="cadaPago" Width="400">
</igDP:UnboundField>
<igDP:Field Label="Colores" Name="Colores" Visibility="Collapsed" />
</igDP:FieldLayout>
</igDP:XamDataGrid.FieldLayouts>
</igDP:XamDataGrid>
`
The code in my viewmodel for the second grid:
public List<ClaseFechasPago> ListaFechasPago
{
get { return listaFechasPago; }
set { listaFechasPago = value; notifyChanges("ListaFechasPago"); }
}
public void PintarFechas(List<ClaseFechasPago> f)
{
ListaFechasPago.Clear();
foreach (ClaseFechasPago fecha in f)
{
fecha.cadaPago = new List<DateTime>();
for (int i = 0; i < fecha.numPagos; i++)
{
fecha.cadaPago.Add(new DateTime());
}
ListaFechasPago.Add(fecha);
}
}
public vmCursos_y_Diplomados()
{
Comando = new cmdCursos_y_Diplomados();
Comando.ViewModel = this;
ListaCursosyDiplomados = new List<ClaseCursosyDiplomados>();
ListaFechasPago = new List<ClaseFechasPago>();
this.cargarDatos();
this.PintarFechas(ListaFechasPago);
}
Now on the command I'm doing the following
public void Execute(object parameter)
{
List<CatEntidadesEducacionContinua> cursos = new List<CatEntidadesEducacionContinua>();
List<ClaseFechasPago> fechas = new List<ClaseFechasPago>();
foreach (ClaseCursosyDiplomados C in ViewModel.ListaCursosyDiplomados.Where(t=>t.Colores==1).ToList())
{
cursos.Add(new CatEntidadesEducacionContinua
{
IdEntidadEducacionContinua = C.id, Coordinador=C.coordinador, Descripcion=C.descripcion, FechaUltimoCambio = DateTime.Now,
FechaInicio = C.fechaInicio, FechaTermino=C.fechaTermino, Precio=C.precio, NumeroDePagos=C.numeroDePagos, FechasPagos=C.fechasPagos, Inhabilitado=C.inhabilitado,
});
if (C.numeroDePagos > 1)
{
ClaseFechasPago f = new ClaseFechasPago();
f.numPagos = C.numeroDePagos;
f.descripcion = C.descripcion;
f.id = C.id;
fechas.Add(f);
}
}
System.Windows.MessageBox.Show(new Entidades.MetodoCursos_y_Diplomados().SetEntidadEContinua(cursos), "Entidades de Educación Continua", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
//System.Windows.MessageBox.Show(new Entidades.MetodoFechasPago().pintarFechasPago
ViewModel.cargarDatos();
ViewModel.PintarFechas(fechas);
}
But as I said it's not working, the execution results in the following screenshot, where the second grid is not populated:
Oh and I also forgot earlier to show the code for my custom class, out of which the list bound to the XamDataGrid is made of:
public class ClaseFechasPago : Utils.PropertyChange
{
private List<DateTime> _cadaPago;
public List<DateTime> cadaPago
{
get { return _cadaPago; }
set
{
_cadaPago = value;
if (EntroPrimeraVez)
{
Colores = 1;
}
}
}
private int? _numPagos;
public int? numPagos
{
get { return _numPagos; }
set
{
_numPagos = value;
if (EntroPrimeraVez)
{
Colores = 1;
}
}
}
private int _id;
public int id
{
get { return _id; }
set
{
_id = value;
}
}
private string _descripcion;
public string descripcion
{
get { return _descripcion; }
set { _descripcion = value; }
}
private int _Colores;
private bool _EntroPrimeraVez;
public bool EntroPrimeraVez
{
get { return _EntroPrimeraVez; }
set { _EntroPrimeraVez = value; notifyChanges("EntroPrimeraVez"); }
}
public int Colores
{
get { return _Colores; }
set { _Colores = value; notifyChanges("Colores"); }
}
}
It turned out the only thing I needed to do was passing the List explicitly as a list, like so:
ListaFechasPago = ListaFechasPago.ToList()
However, I seemed to have a mistake of concept in the way I was building the date fields. I ended up building as many registries as were needed of the same entry and binding a DateTime field to each, like so:
public static List<ClaseFechasPago> PintarFechas(ClaseFechasPago f)
{
List<ClaseFechasPago> ListaFechasPago = new List<ClaseFechasPago>();
for (int i = 0; i < f.numPagos; i++)
{
ClaseFechasPago fecha = new ClaseFechasPago();
fecha.cuotaInscripcion = 0M;
fecha.Inscripcion = true;
fecha.fechaPago = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
fecha.id = f.id;
fecha.descripcion = f.descripcion;
fecha.numPagos = f.numPagos;
fecha.Colores = f.Colores;
fecha.EntroPrimeraVez = f.EntroPrimeraVez;
ListaFechasPago.Add(fecha);
}
return ListaFechasPago;
//ListaFechasPago = ListaFechasPago.ToList();
}
Oh and of course initialize the ListaFechasPago List in the class that is set as DataContext for the window:
ListaFechasPago = new List<ClaseFechasPago>();
insde the class vmCursos_y_Diplomados
because I do:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = new vmCursos_y_Diplomados();
}
I am making a program to check how many courses I have left in my univercity.
I load info from a csv put it's data to a dataset and the display it with a datagrid.
I want some columns(lab and theory) to have checkbox cells so that I can check the courses I passed and then save them back to the csv to load them again later (when I pass somethnig :P).
But I have problem converting those (string) columns to checkboxes as I am not so experienced in c#
That's my code :
string delimiter = ";";
string tablename = "paTable";
filename = "aname";
DataSet dataset = new DataSet();
StreamReader sr = new StreamReader(filename);
DataGridViewColumn column = new DataGridViewColumn();
dataset.Tables.Add(tablename);
dataset.Tables[tablename].Columns.Add("A/A");
dataset.Tables[tablename].Columns.Add("Course");
dataset.Tables[tablename].Columns.Add("Semester");
dataset.Tables[tablename].Columns.Add("Theory");
dataset.Tables[tablename].Columns.Add("Lab");
dataset.Tables[tablename].Columns.Add("Passed");
string alldata = sr.ReadLine();
while (sr.Peek() != -1)
{
alldata = sr.ReadLine();
string[] rows;
rows = alldata.Split("\r".ToCharArray());
foreach (string r in rows)
{
string[] items = r.Split(delimiter.ToCharArray());
dataset.Tables[tablename].Rows.Add(items);
}
this.dataGridView1.DataSource = dataset.Tables[0].DefaultView;
}
Any help would be appreciated !
If you manually created and added the columns to your DataGridView, I think you could keep your DataSet-loading process as is.
Turn off AutoGenerateColumns and add them manually:
dataGridView1.AutoGenerateColumns = false;
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name="Course", ... } );
dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn { Name="Passed", ... } );
...
The grid view should populate after you bind it with your DataView like you're doing:
dataGridView1.DataSource = dataset.Tables[0].DefaultView;
EDIT
Because it relies on strong types and proper binding, a perhaps better alternative would be to create a class to represent a CSV record (types assumed). If this class implements the INotifyPropertyChanged interface the values can be edited in the DataGridView and reflected in the class with minimal effort.
public class CsvDataRow : INotifyPropertyChanged
{
private bool _aa;
private string _course;
private int _semester;
private double _theory;
private double _lab;
private bool _passed;
public bool AA { get { return _aa; } set { if (value == _aa) return; _aa = value; NotifyPropertyChanged("AA"); } }
public string Course { get { return _course; } set { if (value == _course) return; _course = value; NotifyPropertyChanged("Course"); } }
public int Semester { get { return _semester; } set { if (value == _semester) return; _semester = value; NotifyPropertyChanged("Semester"); } }
public double Theory { get { return _theory; } set { if (value == _theory) return; _theory = value; NotifyPropertyChanged("Theory"); } }
public double Lab { get { return _lab; } set { if (value == _lab) return; _lab = value; NotifyPropertyChanged("Lab"); } }
public bool Passed { get { return _passed; } set { if (value == _passed) return; _passed = value; NotifyPropertyChanged("Passed"); } }
char _delimiter;
// static factory method creates object from CSV row
public static CsvDataRow Create(string row, char delimiter)
{
return new CsvDataRow(row, delimiter);
}
// private constructor initializes property values
private CsvDataRow(string row, char delimiter)
{
_delimiter = delimiter;
var values = row.Split(_delimiter);
AA = (values[0].ToString().Equals("1"));
Course = Convert.ToString(values[1]);
Semester = Convert.ToInt32(values[2]);
Theory = Convert.ToDouble(values[3]);
Lab = Convert.ToDouble(values[4]);
Passed = (values[5].ToString().Equals("1"));
}
// a method to convert back into a CSV row
public string ToCsvString()
{
var values = new string[] { (AA ? 1 : 0).ToString(), Course, Semester.ToString(), Theory.ToString(), Lab.ToString(), (Passed ? 1: 0).ToString() };
return string.Join(_delimiter.ToString(), values);
}
// INotifyPropertyChanged interface requires this event
public event PropertyChangedEventHandler PropertyChanged;
// helper method to raise PropertyChanged event
private void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
The CSV file itself could be represented by a class:
public class CsvDataSource
{
public char Delimiter { get; private set; }
public CsvDataSource()
: this(',')
{ }
public string[] Columns { get; private set; }
public ObservableCollection<CsvDataRow> Rows { get; private set; }
public CsvDataSource(char delimiter)
{
Delimiter = delimiter;
}
public void LoadCsv(string csvFileName)
{
string header;
string data;
using (var reader = new StreamReader(csvFileName))
{
header = reader.ReadLine(); // assumes 1st row is column headers
data = reader.ReadToEnd();
}
Columns = header.Split(Delimiter);
var rows = Regex.Split(data, Environment.NewLine);
if (!rows.Select(row => row.Split(Delimiter)).All(row => row.Length == Columns.Length)) throw new FormatException("Inconsistent data format.");
Rows = new ObservableCollection<CsvDataRow>(rows.Select(row => CsvDataRow.Create(row, Delimiter)));
}
}
The DataGridView can then be bound to the Rows property of a CsvDataSource instance, so the form's code can look like this:
public partial class Form1 : Form
{
private CsvDataSource _data;
private ObservableCollection<CsvDataRow> _rows;
public Form1()
{
InitializeComponent();
}
public void LoadCsv(CsvDataSource data)
{
_data = data;
_rows = _data.Rows;
dataGridView1.DataSource = _rows;
}
public void SaveCsv(string path)
{
using (var writer = new StreamWriter(path))
{
writer.WriteLine(string.Join(_data.Delimiter.ToString(), _data.Columns));
foreach (var row in _rows)
{
writer.WriteLine(row.ToCsvString());
}
}
}
}
Of course you'd have a button calling the SaveCsv method, and you'll want another button to add/remove rows to/from your DataGridView. Also you'll want to wrap file I/O operations in a try/cath block.
This is a quickly summed-up implementation that does require a bit of additional work to be fully functional, but it gives an idea, and works out of the box.
This way, the "defining the columns" part is completely taken care of in the CsvDataRow class which provides a strong type for each record. No DataSet, no DataColumn, no DataGridViewColumn either. Just the data, and some data binding.
You can "convert" a textboxcolumn to a checkbox like this:
dgv.Columns.RemoveAt(<NumberColumn2Remove>);
DataGridViewCheckBoxColumn chk = new DataGridViewCheckBoxColumn;
chk.HeaderText = "<HeaderText>";
chk.Name = "<WhatEver>";
chk.DataPropertyName = "<DataField2Bind2>";
dgv.Columns.Insert(<NumberColumn2Insert>, chk);
You need a DataGridViewCheckBoxColumn:
So you need to replace the
DataGridViewColumn column = new DataGridViewColumn();
with the DataGridViewCheckBoxColumn. Have a read this.