Jumping between forms in C# that are in random order - forms

Created a survey style application using forms, it contains 30 forms. For example, the first page asks the user to check which surveys to load, and according to their checks it opens up the correct form. Everything works correctly in one direction. The way I have the program set up is the first page saves static Boolean variables, The control class (Main method), checks if the variables are true or false then opens the corresponding forms. Like this;
if (Survey.r == true || Survey.s == true || SurveySelection.M == true )
{
Form6 newform6 = new Form6();
Form6.Hide();
Form6.ShowDialog();
Form7 newform7 = new Form6();
Form7.Hide();
Form7.ShowDialog();
}
if (Survey.t == true)
{
Form12 newform12 = new Form12();
newform12.Hide();
newform12.ShowDialog();
}
And So on in total 30 forms. The next button on each form just contains this.Hide(), on them.
The problem is if I were to add a back button on this Survey,
I am not sure how to handle it, since the survey is not linear is more logical since it depends on the type of survey the user chooses.
It could load forms 4,19,24,26 in one instance and 3, 6, 9 in other. I need help or guidance implementing a back button to this logic. Any help would be appreciated.

Thirty forms is not a lot. You could create a List and maintain a pointer to the current location.
private InitializeKnowSequence()
{
_formIndex = 0;
_formsList.Add(new Form2());
_formsList.Add(new Form2());
_formsList.Add(new Form3());
_formsList.Add(new Form4());
}
private void NavigatePrior()
{
if (_formIndex > 0)
{
_formsList[_formIndex--].Hide();
_formsList[_formIndex].Show();
}
}
private void NavigateNext()
{
if(_formIndex<_formsList.Count()-1)
{
_formsList[_formIndex++].Hide();
_formsList[_formIndex].Show();
}
}
Then add a PushForm(Form form) method for logical branches forward
private void PushForm(Form form)
{
_formsList.Add(form);
NavigateNext();
}

Related

Fabric Modding: Modifying the Enchantment Table using Mixins

I'm trying to add a new book item, that can be enchanted just like normal books, but that have a higher enchantability. Everything works so far, just one thing is missing: When you enchant normal books, they get converted to Enchanted Books. The code that does that, is located in the onButtonClick method of the EnchantmentScreenHandler class:
public boolean onButtonClick(PlayerEntity player, int id) {
if (id >= 0 && id < this.enchantmentPower.length) {
//...
if (//...) {
return false;
} else if (//...) {
return false;
} else {
this.context.run((world, pos) -> {
//...
if (//...) {
player.applyEnchantmentCosts(itemStack, i);
boolean bl = itemStack.isOf(Items.BOOK); //<--- "bl" is the important variable
if (bl) {
itemStack3 = new ItemStack(Items.ENCHANTED_BOOK);
NbtCompound nbtCompound = itemStack.getNbt();
if (nbtCompound != null) {
itemStack3.setNbt(nbtCompound.copy());
}
this.inventory.setStack(0, itemStack3);
}
}
So if the item that gets enchanted, is a Book, it gets later replaced with an Enchanted Book. So my idea was to just modify the assigment of bl using the #ModifyVariable annotation and then check, if the item is made of my modded book. But whatever I try, I can't get it to work. I always get the error No refMap loaded.. I figured it's not working, because the variable bl is located inside a lambda function, but I'm not sure if that's really the issue. Of course I can just replace the entire body of the method, but that wouldn't be good for compatibility with other mods.

Manatee.Trello Moving Cards

I'm writing a small application to manage Trello Boards in only a few aspects such as sorting Cards on a List, moving/copying Cards based on Due Date and/or Labels, archiving Lists on a regular basis and generating reports based on Labels, etc. As such, I've been putting together a facade around the Manatee.Trello library to simplify the interface for my services.
I've been getting comfortable with the library and things have been relatively smooth. However, I wrote an extension method on the Card class to move Cards within or between Lists, and another method that calls this extension method repeatedly to move all Cards from one List to another.
My issue is that when running the code on a couple of dummy lists with 7 cards in one, it completes without error, but at least one card doesn't actually get moved (though as many as 3 cards have failed to move). I can't tell if this is because I'm moving things too rapidly, or if I need to adjust the TrelloConfiguration.ChangeSubmissionTime, or what. I've tried playing around with delays but it doesn't help.
Here is my calling code:
public void MoveCardsBetweenLists(
string originListName,
string destinationListName,
string originBoardName,
string destinationBoardName = null)
{
var fromBoard = GetBoard(originBoardName); // returns a Manatee.Trello.Board
var toBoard = destinationBoardName == null
|| destinationBoardName.Equals(originBoardName, StringComparison.OrdinalIgnoreCase)
? fromBoard
: GetBoard(destinationBoardName);
var fromList = GetListFromBoard(originListName, fromBoard); // returns a Manatee.Trello.List from the specified Board
var toList = GetListFromBoard(destinationListName, toBoard);
for (int i = 0; i < fromList.Cards.Count(); i++)
{
fromList.Cards[i].Move(1, toList);
}
}
Here is my extension method on Manatee.Trello.Card:
public static void Move(this Card card, int position, List list = null)
{
if (list != null && list != card.List)
{
card.List = list;
}
card.Position = position;
}
I've created a test that replicates the functionality you want. Basically, I create 7 cards on my board, move them to another list, then delete them (just to maintain initial state).
private static void Run(System.Action action)
{
var serializer = new ManateeSerializer();
TrelloConfiguration.Serializer = serializer;
TrelloConfiguration.Deserializer = serializer;
TrelloConfiguration.JsonFactory = new ManateeFactory();
TrelloConfiguration.RestClientProvider = new WebApiClientProvider();
TrelloAuthorization.Default.AppKey = TrelloIds.AppKey;
TrelloAuthorization.Default.UserToken = TrelloIds.UserToken;
action();
TrelloProcessor.Flush();
}
#region http://stackoverflow.com/q/39926431/878701
private static void Move(Card card, int position, List list = null)
{
if (list != null && list != card.List)
{
card.List = list;
}
card.Position = position;
}
[TestMethod]
public void MovingCards()
{
Run(() =>
{
var list = new List(TrelloIds.ListId);
var cards = new List<Card>();
for (int i = 0; i < 10; i++)
{
cards.Add(list.Cards.Add("test card " + i));
}
var otherList = list.Board.Lists.Last();
for(var i = 0; i < cards.Count; i++)
{
Move(card, i, otherList);
}
foreach (var card in cards)
{
card.Delete();
}
});
}
#endregion
Quick question: Are you calling TrelloProcessor.Flush() before your execution ends? If you don't, then some changes will likely remain in the request processor queue when the application ends, so they'll never be sent. See my wiki page on processing requests for more information.
Also, I've noticed that you're using 1 as the position for each move. By doing this, you'll end up with an unreliable ordering. The position data that Trello uses is floating point. To position a card between two other cards, it simply takes the average of the other cards. In your case, (if the destination list is empty), I'd suggest sending in the indexer variable for the ordering. If the destination list isn't empty, you'll need to calculate a new position based on the other cards in the list (by the averaging method Trello uses).
Finally, I like the extension code you have. If you have ideas that you think would be useful to add to the library, please feel free to fork the GitHub repo and create a pull request.

How to pass more than one record between two forms?

I want to pass more than one record between two forms. The user opens Form-A, selects multiple records and then clicks a button that opens Form-B.
In Form-B there are two (or more) StringEdit controls and they should display values from the selected records.
I know how to pass only one record, to do that I use the following code in a method of Form-B:
if (element.args().parmEnumType() == enumNum(NoYes)
&& element.args().parmEnum() == NoYes::Yes)
{
myTable = element.args().record();
stringEdit.text(myTable.Field);
}
How should I change my code so that I can set the text of another StringEdit control to the field value of the next record that the user selected?
To do this, you can use an args to pass the records, which you will need to prepare in your Form-A, as below (taking the SalesTable as example);
int recordsCount;
SalesTable salesTable;
container con;
Args args = newArgs();
// gets the total records selected
recordsCount = salesTable_ds.recordsMarked().lastIndex();
salesTable = salesTable_ds.getFirst(1);
while(salesTable)
{
// storing recid of selected record in container
con = conIns(con,1, salesTable.RecId);
salesTable = SampleTable_ds.getNext(); // moves to next record
}
// passing container converted to string
args.parm(con2Str(con,','));
Then on your Form-B, you will need to override the init() method to read the args you created,
In order to retrieve passed arguments in the recipient from. Override the init() method of new form as shown
public void init()
{
container con;
int i;
super();
// string to container
con = str2con(element.args().parm(),'','');
// for sorting
for(i = 1;i<= conLen(con) ;i++)
{
salesTable_ds.query().dataSourceTable(Tablenum(SalesTable)).addRange(fieldNum(SalesTable,RecId)).value(SysQuery::value(conPeek(con,i)));
}
}
Hope it helps.
Taken from Ax-Forum
This will typically imply looping through the selected records in Form-A and changing the query in Form-B.
The idiomatic way to loop through selected records involves a for loop and the getFirst and getNext methods of the datasource:
SalesLine sl;
FormDataSourcs ds = _salesLine.dataSource();
for (sl = ds.getFirst(true) ? ds.getFirst(true) : ds.cursor(); sl; sl = ds.getNext())
{
//Do your thing, add a query range
}
The MultiSelectionHelper class may be of use here, as it does the thing:
public void init()
{
MultiSelectionHelper ms;
super();
if (element.args() && element.args().caller() && element.args().record())
{
this.query().dataSourceTable(tableNum(SalesLine)).clearDynalinks();
ms = MultiSelectionHelper::createFromCaller(element.args().caller());
ms.createQueryRanges(this.query().dataSourceTable(tablenum(SalesLine)), fieldstr(SalesLine, InventTransId));
}
}

Is there an Update Object holder on Entity Framework?

I'm currently inserting/updating fields like this (if there's a better way, please say so - we're always learning)
public void UpdateChallengeAnswers(List<ChallengeAnswerInfo> model, Decimal field_id, Decimal loggedUserId)
{
JK_ChallengeAnswers o;
foreach (ChallengeAnswerInfo a in model)
{
o = this.FindChallengeAnswerById(a.ChallengeAnswerId);
if (o == null) o = new JK_ChallengeAnswers();
o.answer = FilterString(a.Answer);
o.correct = a.Correct;
o.link_text = "";
o.link_url = "";
o.position = FilterInt(a.Position);
o.updated_user = loggedUserId;
o.updated_date = DateTime.UtcNow;
if (o.challenge_id == 0)
{
// New record
o.challenge_id = field_id; // FK
o.created_user = loggedUserId;
o.created_date = DateTime.UtcNow;
db.JK_ChallengeAnswers.AddObject(o);
}
else
{
// Update record
this.Save();
}
}
this.Save(); // Commit changes
}
As you can see there is 2 times this.Save() (witch invokes db.SaveChanges();)
when Adding we place the new object into a Place Holder with the AddObject method, in other words, the new object is not committed right away and we can place as many objects we want.
But when it's an update, I need to Save first before moving on to the next object, is there a method that I can use in order to, let's say:
if (o.challenge_id == 0)
{
// New record
o.challenge_id = field_id;
o.created_user = loggedUserId;
o.created_date = DateTime.UtcNow;
db.JK_ChallengeAnswers.AddObject(o);
}
else
{
// Update record
db.JK_ChallengeAnswers.RetainObject(o);
}
}
this.Save(); // Only save once when all objects are ready to commit
}
So if there are 5 updates, I don't need to save into the database 5 times, but only once at the end.
Thank you.
Well if you have an object which is attached to the graph, if you modify values of this object, then the entity is marked as Modified.
If you simply do .AddObject, then the entity is marked as Added.
Nothing has happened yet - only staging of the graph.
Then, when you execute SaveChanges(), EF will translate the entries in the OSM to relevant store queries.
Your code looks a bit strange. Have you debugged through (and ran a SQL trace) to see what is actually getting executed? Because i can't see why you need that first .Save, because inline with my above points, since your modifying the entities in the first few lines of the method, an UPDATE statement will most likely always get executed, regardless of the ID.
I suggest you refactor your code to handle new/modified in seperate method. (ideally via a Repository)
Taken from Employee Info Starter Kit, you can consider the code snippet as below:
public void UpdateEmployee(Employee updatedEmployee)
{
//attaching and making ready for parsistance
if (updatedEmployee.EntityState == EntityState.Detached)
_DatabaseContext.Employees.Attach(updatedEmployee);
_DatabaseContext.ObjectStateManager.ChangeObjectState(updatedEmployee, System.Data.EntityState.Modified);
_DatabaseContext.SaveChanges();
}

How can I tell if a <script> tag with a given src attribute is present on the page in ASP.net?

Like the title says, I'm trying to find out if I need to include a script library that my ASP.net UserControl needs to work. I don't want to include it multiple times per page, but I want my control to be able to be used multiple times on the same page.
How can I, in the codebehind of my control, check to see if a given <script/> tag is present?
This is .Net 2.0, no LINQ.
If !Page.ClientScript.IsClientScriptIncludeRegistered("jQuery")
Page.ClientScript.RegisterClientScriptInclude("jQuery", "/scripts/jquery.js");
or if you need a script block, And want to include the control's type:
if (!Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), "myScript"))
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "myScript"
, "<script>alert('xx');</script>", false);
This might be a bit overkill for your usage, but I'm using it to search for existing CSS and JS before adding to the page:
private static bool HeaderLinkExists(Page page, string path)
{
path = path.ToLowerInvariant();
foreach (Control c in page.Header.Controls)
{
if (c is HtmlLink)
{
// stylesheet (or other links), check href
HtmlLink link = (HtmlLink)c;
if (link.Href.ToLowerInvariant().Contains(path))
{
return true;
}
}
else if (c is HtmlGenericControl)
{
// any generic html tag, check for src or href
HtmlGenericControl hgc = (HtmlGenericControl)c;
if ((!string.IsNullOrEmpty(hgc.Attributes["src"]) && hgc.Attributes["src"].ToLowerInvariant().Contains(path)) || (!string.IsNullOrEmpty(hgc.Attributes["href"]) && hgc.Attributes["href"].ToLowerInvariant().Contains(path)))
{
return true;
}
}
else if (c is LiteralControl)
{
// scripts or other html literal controls, use regex to look for src or hrefs and check each one
LiteralControl lit = (LiteralControl)c;
if (MatchLiteralText(lit.Text, path))
{
return true;
}
}
else if (c is Literal)
{
// similar to above, use regex to look for src or hrefs and check each one
Literal lit = (Literal)c;
if (MatchLiteralText(lit.Text, path))
{
return true;
}
}
}
return false;
}
private static readonly Regex linkMatcher = new Regex(#"(?:src|href)\s*=\s*([""']?)(?<LinkValue>[^\1]+?)[\1>]", RegexOptions.Compiled);
private static bool MatchLiteralText(string text, string path)
{
if (!string.IsNullOrEmpty(text))
{
text = text.ToLowerInvariant()
foreach (Match m in linkMatcher.Matches(text))
{
if (m.Groups["LinkValue"].Value.Contains(path))
{
return true;
}
}
}
return false;
}
// usage:
if (!HeaderLinkExists(page, "/css/controlstyles.css"))
{
HtmlHeadUtility.RegisterStylesheetInHeader(page, "~/css/controlstyles.css");
}
if (!HeaderLinkExists(page, "/js/controlscript.js"))
{
HtmlHeadUtility.RegisterClientScriptIncludeInHeader(page, "~/js/controlscript.js");
}
It works great if you're sure that the LINK or SCRIPT is guaranteed to be in the HEAD.
No, there isn't.
Instead, you should maintain a set of <script> tags that have already been included, and update it whenever you add a script. (For example, a [ThreadStatic] static List<String>)
I would suggest re-thinking your problem/solution. It seems like what you are trying to do would couple your user control and the pages that use it. This would require that a page reference that script in order to use a control.
Is there any reason you can't just put the script tag in your user control so that the pages consuming your user control don't need to know that they need to include a specific script tag to work?
I tend to think that if you want to just use a control you should be able to just use it.