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))
Related
I have a list mentioned below.
var fakedata = new Dictionary<Gateway, List<FeMeasurementValues>>()
{
{
new Gateway { SiteId = 1, FirmwareVersion = "1.1.1", ConnectivityStatus = GatewayConnectivityStatus.ReadyToConnect },
new List<FeMeasurementValues>() { new FeMeasurementValues { MeasurementName = "MsgLRRID", Values = new List<FeValue> { new FeValue { Value = "FFFF123", Horodate = DateTime.Now } } } }
},
{
new Gateway { SiteId = 2, FirmwareVersion = "1.1.2", ConnectivityStatus = GatewayConnectivityStatus.Connected },
new List<FeMeasurementValues>() { new FeMeasurementValues { MeasurementName = "MsgLRRID", Values = new List<FeValue> { new FeValue { Value = "GH67123", Horodate = DateTime.Now } } } }
},
{
new Gateway { SiteId = 3, FirmwareVersion = "1.1.3", ConnectivityStatus = GatewayConnectivityStatus.Disconnected },
new List<FeMeasurementValues>() { new FeMeasurementValues { MeasurementName = "MsgLRRID", Values = new List<FeValue> { new FeValue { Value = " ", Horodate = DateTime.Now } } } }
},
{
new Gateway { SiteId = 4, FirmwareVersion = "1.1.1", ConnectivityStatus = GatewayConnectivityStatus.Connected },
new List<FeMeasurementValues>() { new FeMeasurementValues { MeasurementName = "MsgLRRID", Values = new List<FeValue> { new FeValue { Value = "SA67123", Horodate = DateTime.Now } } } }
}
};
I have two methods
"GetPublicNetworkUsedCount()" which needs to return the count of Value which starts with "FFFF"
So, In this case output should be 1.
"GetPrivateNetworkUsedCount()" which needs to return the count of Value which does not starts with "FFFF" and which includes empty values.
So, In this case output should be 3.
Below is what i have tried:
private static string GetPublicNetworkUsedCount(List<FeValue> values)
{
var countofPublicNetwork = values.Where(x => x.Value.Any(f => x.Value.StartsWith("FFFF")));
return countofPublicNetwork.Count().ToString();
}
private static string GetPrivateNetworkUsedCount(List<FeValue> values)
{
var countofPrivateNetwork = values.Where(x => x.Value.Any(f => !x.Value.StartsWith("FFFF")));
return countofPrivateNetwork.Count().ToString();
}
I'm getting the wrong output as 0 for GetPublicNetworkUsedCount and 1 for GetPrivateNetworkUsedCount.
Please help me.
x.Value.Any() will return true as soon as the condintion inside is true. which leads to return 1 convertet to a number.
to get alll entries starting with FFFF remove the Any part like:
var countofPublicNetwork = values.Where(x =>x.Value.StartsWith("FFFF"));
you can get the count directly if you substitute .Where() with .Count() like Mark mentioned in his comment.
var countofPublicNetwork = values.Count(x =>x.Value.StartsWith("FFFF"));
You have a List<FeValue>, where each object has a string Value. You are treating the string as a collection and going one step to deep, the .Any( is not needed.
So the check should just be
values.Where(x => x.Value.StartsWith("FFFF")).Count();
Or just
values.Count(x => x.Value.StartsWith("FFFF"));
See comments:
// vv I'd recommend to return int
private static string GetPublicNetworkUsedCount(List<FeValue> values)
{ // vv Any doesn't make sense here: this is a string
var countofPublicNetwork = values.Where(x => x.Value.Any(f => x.Value.StartsWith("FFFF")));
return countofPublicNetwork.Count().ToString();
}
private static string GetPrivateNetworkUsedCount(List<FeValue> values)
{
var countofPrivateNetwork = values.Where(x => x.Value.Any(f => !x.Value.StartsWith("FFFF")));
return countofPrivateNetwork.Count().ToString();
}
So, I'd do something like this:
private static int GetPublicNetworkUsedCount(List<FeValue> values)
=> values.Count(x => x.Value.StartsWith("FFFF"));
private static int GetPrivateNetworkUsedCount(List<FeValue> values)
=> values.Count(x => !x.Value.StartsWith("FFFF"));
The returned int can then be stringyfied if need be.
Maybe I'd even do
public static class FeValueListExtensions
{
public static int GetPublicNetworkUsedCount(this List<FeValue> values)
=> values.Count(x => x.Value.StartsWith("FFFF"));
public static int GetPrivateNetworkUsedCount(this List<FeValue> values)
=> values.Count(x => !x.Value.StartsWith("FFFF"));
}
which can then be used as
// Assume we have a List<FeValue> defined as
List<FeValue> feValues = ...
var publicCount = feValues.GetPublicNetworkUsedCount();
I'm trying to understand why this test fails with:
Maak.Test.InitializeNewUnitTest.NoPropertiesInitialized_Diagnostic
Assert.AreEqual failed. Expected:<37>. Actual:<38>. Context:
Diagnostics of test state Expected diagnostic to end at column "38"
was actually at column "39"
Expected diagnostic:
// /0/Test0.cs(13,9,13,38): warning MaakInitializeNew VerifyCS.Diagnostic().WithSpan(13, 9, 13, 38),
Actual diagnostic:
// /0/Test0.cs(13,9): warning MaakInitializeNew: can be fully initialized VerifyCS.Diagnostic().WithSpan(13, 9, 13, 39),
The test:
[TestMethod]
public async Task NoPropertiesInitialized_Diagnostic()
{
await VerifyCS.VerifyCodeFixAsync(#"
using System;
public class MyClass
{
public string Name { get; set; }
}
class Program
{
static void Main()
{
[|var myClass = new MyClass { }|];
}
}
", #"
using System;
public class MyClass
{
public string Name { get; set; }
}
class Program
{
static void Main()
{
var myClass = new MyClass { Name = ""Stan"" };
}
}
");
}
The analyzer code:
public override void Initialize(AnalysisContext context)
{
// See https://github.com/dotnet/roslyn/blob/main/docs/analyzers/Analyzer%20Actions%20Semantics.md for more information
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.LocalDeclarationStatement);
}
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var localDeclaration = (LocalDeclarationStatementSyntax)context.Node;
var typeDeclaration = localDeclaration.Declaration.Type;
var symbolInfo = context.SemanticModel.GetSymbolInfo(typeDeclaration);
var typeSymbol = symbolInfo.Symbol;
if(typeSymbol == null)
return;
// Special case: Ensure that 'var' isn't actually an alias to another type. (e.g. using var = System.String).
var aliasInfo = context.SemanticModel.GetAliasInfo(typeDeclaration);
if (aliasInfo != null)
return;
var namedSymbol = context.Compilation.GetTypeByMetadataName(typeSymbol.MetadataName);
if (namedSymbol?.TypeKind != TypeKind.Class)
return;
var hasDefaultConstructor = (namedSymbol?.Constructors)?.SingleOrDefault(c => !c.Parameters.Any()) != null;
var properties = namedSymbol?.GetMembers()
.Where(m => m.Kind == SymbolKind.Property
&& m.DeclaredAccessibility == Accessibility.Public
&& !((IPropertySymbol)m).IsReadOnly
&& !((IPropertySymbol)m).IsStatic)
.Select(m => new
{
Name = m.Name,
Type = ((IPropertySymbol)m).Type
})
.ToList();
var hasValidProperties = properties?.Any() != false;
if (!hasValidProperties)
return;
var initializerExpressions = (localDeclaration.Declaration.Variables.FirstOrDefault().Initializer.Value
as ObjectCreationExpressionSyntax)?.Initializer.Expressions.ToList();
var except = properties.Select(p => p.Name)
.Except(initializerExpressions.Select(e => (e as AssignmentExpressionSyntax)?.Left.ToString()))
.ToList();
if(except.Count == 0)
return;
context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.GetLocation()));
}
Reporting the correct location fixed it:
context.ReportDiagnostic(Diagnostic.Create(Rule, localDeclaration.Declaration.GetLocation()));
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 need to set the property SortOrder in the GridEx,
and this property is only get.
What can I do?
the code:
private void M_Grid_ColumnHeaderClick(object sender, Janus.Windows.GridEX.ColumnActionEventArgs e)
{
if (e.Column.DataMember == "Filed1")
{
var list = m_Grid.DataSource;
if (e.Column.SortOrder == Janus.Windows.GridEX.SortOrder.Descending)
{
list = list.OrderBy(p => p.ParticipationDate).ToList();
e.Column.SortOrder = Janus.Windows.GridEX.SortIndicator.Ascending;// it's not good
}
else
{
list = list.OrderByDescending(p => p.ParticipationDate).ToList();
e.Column.SortOrder = Janus.Windows.GridEX.SortIndicator.Descending;// it's not good
}
m_Grid.DataSource = list;
}
}
Not recommended way:
private void M_Grid_ColumnHeaderClick(object sender, Janus.Windows.GridEX.ColumnActionEventArgs e)
{
if (e.Column.DataMember == "Filed1")
{
var list = m_Grid.DataSource;
if (e.Column.SortOrder == Janus.Windows.GridEX.SortOrder.Descending)
{
list = list.OrderBy(p => p.ParticipationDate).ToList();
// e.Column.SortOrder = Janus.Windows.GridEX.SortIndicator.Ascending;
}
else
{
list = list.OrderByDescending(p => p.ParticipationDate).ToList();
// e.Column.SortOrder = Janus.Windows.GridEX.SortIndicator.Descending;
}
m_Grid.DataSource = list;
m_Grid.Refetch();
}
}
Another approach working with sortkeys for example:
private void M_Grid_ColumnHeaderClick(object sender, Janus.Windows.GridEX.ColumnActionEventArgs e)
{
if (e.Column.DataMember == "Filed1")
{
//Removing any sort key that may be present in the table
m_Grid.RootTable.SortKeys.Clear(); //or can be removed only specific
// sortkey
// get the column to be sorted
column = e.Column;
if (e.Column.SortOrder == Janus.Windows.GridEX.SortOrder.Descending)
{
sortKey = new GridEXSortKey(column, SortOrder.Ascending);
}
else
{
sortKey = new GridEXSortKey(column, SortOrder.Descending);
}
m_Grid.RootTable.SortKeys.Add(sortKey);
}
}
After a lot of experimenting and being the right answer.
In case you want to sort a particular field by any other value and not by default
Use the property: SortComparer and implement the Compare() function of the IComparer class
For example, what I did is:
On the load of the component write:
m_Grid.RootTable.Columns["Field1"].SortComparer = new Field1Sort();
The class to implement:
public class Field1Sort: IComparer
{
public Field1Sort()
{
}
public int Compare(object x, object y)
{
var xString = (string)x;
var yString = (string)y;
var date1 = xString.Substring(0, 10).ToDateTime();
var date2 = yString.Substring(0, 10).ToDateTime();
if (date1 < date2)
return -1;
if (date1 > date2)
return 1;
else
return 0;
}
}
I'm having trouble converting a Query Expression found here: http://www.oak3.org/crm/workflow-activity-checking-duplicate-instances/
into a linq query. To put it simply, the goal is if two workflows get triggered at the same time, only let one go through sorted by most recent. Currently my linq version will sometimes cancel a workflow even if it is the only one running. I know I need to utilize the input parameter somehow (to tell it what workflow to compare to), and I'm sure there could be more issues. Any help is greatly appreciated.
[Input("Current workflow")]
[ReferenceTarget("workflow")]
public InArgument<EntityReference> workflowReferenceInput { get; set; }
[Output("Is first workflow")]
public OutArgument<Boolean> isFirstWorkflow { get; set; }
protected override void Execute(CodeActivityContext executionContext)
{
ITracingService tracer = executionContext.GetExtension<ITracingService>();
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
Entity entity = (Entity)context.InputParameters["Target"];
isFirstWorkflow.Set(executionContext, false);
var wfReference = workflowReferenceInput.Get(executionContext);
var wfEntity = service.Retrieve("workflow", wfReference.Id, new ColumnSet ( "name" ));
ConditionExpression ce1 = new ConditionExpression();
ce1.AttributeName = "statuscode";
ce1.Operator = ConditionOperator.In;
ce1.Values.Add(0);
ce1.Values.Add(10);
ce1.Values.Add(20);
ce1.Values.Add(21);
ce1.Values.Add(22);
FilterExpression fe1 = new FilterExpression();
fe1.Conditions.Add(ce1);
QueryExpression qe = new QueryExpression();
qe.EntityName = AsyncOperation.EntityLogicalName;
qe.ColumnSet = new ColumnSet();
qe.Criteria = new FilterExpression();
qe.Criteria.AddFilter(fe1);
var childFilter = qe.Criteria.AddFilter(LogicalOperator.And);
childFilter.AddCondition("operationtype", ConditionOperator.Equal, 10);
childFilter.AddCondition("name", ConditionOperator.Equal, wfEntity["name"]);
LinkEntity link = new LinkEntity
{
LinkFromEntityName = AsyncOperation.EntityLogicalName,
LinkToEntityName = Quote.EntityLogicalName,
LinkFromAttributeName = "regardingobjectid",
LinkToAttributeName = "quoteid"
};
link.LinkCriteria.AddCondition("quoteid", ConditionOperator.Equal, context.PrimaryEntityId.ToString());
DataCollection<Entity> result = service.RetrieveMultiple(qe).Entities;
var list = result.ToList().OrderBy(c => c.Id);
for (var i = 0; i < list.Count(); i++)
{
var item = list.ElementAt(i);
if(item.Id == context.OperationId && i == 0)
{
isFirstWorkflow.Set(executionContext, true);
}
}
}
catch (Exception e)
{
throw new InvalidPluginExecutionException(e.Message);
}
}
into this:
public class WorkflowChecker: CodeActivity
{
[Input("Current workflow")]
[ReferenceTarget("workflow")]
public InArgument<EntityReference> workflowReferenceInput { get; set; }
[Output("Is first workflow")] public OutArgument<Boolean> isFirstWorkflow { get; set; }
protected override void Execute(CodeActivityContext executionContext)
{
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
try
{
var ok = WorkflowChecker(context.PrimaryEntityId, context.OperationId);
isFirstWorkflow.Set(executionContext, ok);
}
catch (Exception e)
{
throw new InvalidPluginExecutionException(e.Message);
}
}
}
which calls:
public static bool WorkflowChecker(Guid workflowContextId,
Guid asyncOperationId)
{
var someReturnValue = false;
var listOfWorkflowIds = new List<Guid>();
try
{
var query = from async in AsyncOperationSet
join b in BSet on async.RegardingObjectId.Id equals b.Id
where b.Id.Equals(workflowContextId)
&& (async.StateCode.Equals(0)
|| async.StateCode.Equals(1)
|| async.StateCode.Equals(2))
select new {async.AsyncOperationId};
foreach (var x in query)
{
if (x.AsyncOperationId != Guid.Empty)
{
listOfWorkflowIds.Add(x.AsyncOperationId.Value);
}
}
listOfWorkflowIds.Sort();
if (listOfWorkflowIds.First() == asyncOperationId)
{
someReturnValue = true;
}
}
catch (Exception e)
{
Console.WriteLine("Error in Workflow Checker: " + e);
}
return someReturnValue;
}
I've added the following lines to the workflow library then passed the parameter into the call to compare by name and so far it appears to be working successfully:
var wfReference = workflowReferenceInput.Get(executionContext);
var wfEntity = service.Retrieve("workflow", wfReference.Id, new ColumnSet("name"));
var test = wfEntity["name"];