MudBlazor Timeline add item with different variables - c#

<MudTimeline TimelineOrientation="TimelineOrientation.Horizontal" TimelinePosition="TimelinePosition.Alternate" >
#for (int i = 0; i < allBookings.Count - 3; i += 3)
{
//bookString.Add(allBookings[i + 1]);
<MudTimelineItem Color="Color.Error" Variant="Variant.Filled">
<ItemContent>
<MudAlert Severity="Severity.Error">#allBookings[i+1]</MudAlert>
</ItemContent>
<ItemOpposite>
<MudText Color="Color.Error">#allBookings[i]</MudText>
</ItemOpposite>
</MudTimelineItem>
}
</MudTimeline>
I want to add a new timeline item when a new booking is added. But the loop will always make all the previous bookings to the same value as the last one. I tried to move the loop functions around, but either it doesn't work the way I wanted or it simply doesn't allow it.
I also tried to make a new list to store all the existing customers and compare it, but that didn't work out either.
I know this is more of a logic problem than a programmatic one, but please send help.

This is the classic problem of using for loop. The problem is that you're passing i (declared inside the for) which is just one variable that will be incremented in each iteration.
The HTML content will be rendered when the for loop is executed, but the event handlers is called later, which means that the i will not have the value you're expecting.
This problem is not even related with Blazor, it's more related with C# in general.
To solve you problem you must save the i variable in a "local" variable first.
<MudTimeline TimelineOrientation="TimelineOrientation.Horizontal" TimelinePosition="TimelinePosition.Alternate" >
#for (int i = 0; i < allBookings.Count - 3; i += 3)
{
var index = i;
<MudTimelineItem Color="Color.Error" Variant="Variant.Filled">
<ItemContent>
<MudAlert Severity="Severity.Error">#allBookings[index+1]</MudAlert>
</ItemContent>
<ItemOpposite>
<MudText Color="Color.Error">#allBookings[index]</MudText>
</ItemOpposite>
</MudTimelineItem>
}
</MudTimeline>
Here I provide a small example of what I just said!
https://try.mudblazor.com/snippet/GawGYhljyIczxjrY

Related

How can you add an integer to the value of 'i' in a for loop?

I have a C# for loop incorporated as razor code into a webpage. This HTML segment will be generated
until the condition (i < Model.RecentArticles.Count) becomes false. But if you know anything about for loops you probably already knew that.
My issue is that I wish to set the IDs of the div element to be like such: grid_1, grid_2, grid_3, etc. for each consecutive div the code produces.
However since i starts as 0 (this cannot be changed because doing so would skip the first row in the database) the divs will be given the IDs grid_0, grid_1, grid_2, etc.
I figured this would be easy to fix, I would just change the razor code in the ID parameter to read id="grid_#{i+1;}". Unfortunately, this results in an error and have no idea whether I have made some sort of syntax error or if what I am trying to do it not possible. I am very new to C# and razor so I suspect I have just made a silly mistake somewhere.
#for (int i = 0; i < Model.RecentArticles.Count; i++)
{
<div class='section_list' id="grid_#{i+1;}">Article</div>
}
This should work:
#for (int i = 0; i < Model.RecentArticles.Count; i++)
{
<div class='section_list' id="grid_#(i + 1)">Article</div>
}

Problem with foreach loop giving values to a button in Unity

I'm trying to do a Candy Crush-like map for my game in Unity, I'm trying to gather all the buttons in an array and then set its onclick property so when I click on them I get to the level I want. I'm using a Foreach loop to achieve it.
The problem is that on every single button, I get to load the same scene. It does list my levels from 1 to N but the onclick does not seem to be working fine! I've tried doing a for loop instead foreach but it doesn't work either.
int i = 0;
foreach(GameObject level in levels)
{
level.GetComponent<Button>().onClick.AddListener(() => SceneManager.LoadScene(i + 1));
i++;
}
You've created a closure on a loop variable. A common pitfall, for sure. A suitable explanation and remedy for this kind of problem already exists on StackOverflow.
When you use the symbol i, it is essentially a reference to the one and only i that existed outside of your loop. Its value, by the time any of the listeners get invoked, will be the value it had at the end of the loop, which, in your case, would be the number of levels you have.
To avoid this, you need to use the value of i, not a reference to the variable. You can do this by creating a new variable that will have scope unique to one iteration of the loop and passing in that new variable's value. Basically a copy of i is what you need.
The essence of the necessary change would be:
int i = 0;
foreach(GameObject level in levels)
{
int copy_of_i = i;
level.GetComponent<Button>().onClick.AddListener(() => SceneManager.LoadScene(copy_of_i + 1));
i++;
}
I think the problem is the lambda expression:
() => SceneManager.LoadScene(i + 1)
you it is not the value of i, but instead the variable i, which will get incremented again
over the other iterations so when you click on it
SceneManager.LoadScene(i + 1); gets called, but i is now 25 or whatever your level number is.
Create a temporary variable directly before it so each lambda expression gets their own variable
int tmp = i;
level.GetComponent().onClick.AddListener(() =>SceneManager.LoadScene(tmp + 1));

Increment through a list on a button list

I've stored a list of colors in my program. I am after an object in my scene to one of the colors in the list. So far, I have done the followings:
if(Input.GetKeyDown(KeyCode.O))
{
for(int i = 0; i < claddingColor.Count; i++)
{
claddingMaterial.color = claddingColor[i];
}
}
This isn't working due to a reason I know (and you can probably spot) but I lack to the verbal fortitude to write it down.
As opposed to have a multiple lines of the following:
claddingMaterial.color = claddingColor[0];
Each tied to different buttons, I like a way I can emulate the above but tie it to a single button press. Thus, if I hit the 0 button 5 times, it will loop through each color stored in the list. If I hit it for a sixth time, it will go back to the first color in the list.
Could someone please help me implement this? Or point me to something that I may learn how to do it for myself?
Define LastColor property as class member:
int LastColor;
In your function use modulo
if(Input.GetKeyDown(KeyCode.O))
{
claddingMaterial.color = claddingColor[(LastColor++) % claddingColor.Count];
}
Note: Depending on the type of claddingColor use Count for a List or Length for Array.
You won't need a for loop
int lastStep = 0;
if(Input.GetKeyDown(KeyCode.O))
{
claddingMaterial.color = claddingColor[lastStep++];
if (lastStep == claddingColor.Count)
lastStep = 0;
}

Iterating over an array using index and assigning values depending on index

I was facing this problem earlier today, and since I could not find a satisfactory solution, I decided to change my class design, and have seperate properties such as Tag 1, Tag 2, Tag 3 etc.
My main problem is the fact that I need to bind a grid to an object that contains a list among other properties and I need to show each item in the list as a separate column which I am unable to do. Hence I am resorting to declaring variables separately. Original question is here...
Now, I'm facing one of the most common design problem that probably every programmer has at some point of time. Here is the code to demonstrate it,
for (int i = 0; i < tags.Length; ++i) // Length not known here.
{
if(i==0){
tag1 = tags[0];
}
else if(i == 1){
tag2 = tags[1];
}
else if(i == 2){
tag3 = tags[2];
}
....
}
Here tags is a string array.
I was wondering if there is a more elegant way to do this. Another thing to note is that the efficiency of this loop decreases as it progresses, since with more iterations it has to check more conditions. If we could remove a condition after it had become true once it would speed up each iteration since we know that each condition will become true only once in all the iterations
Moved answer about DataGridView and using ComponentModel to the correct question:
Displaying a list of object containing a list in a grid view
Briefing
The DataGridView controll supports the ComponentModel namespace so that you can create classes that appear to have properties that don't exist. It is the same mechanism the PropertyGrid uses.
The sample code is in this answer of that question:
https://stackoverflow.com/a/13078735/195417
OLD ANSWER
This was my previous answer, when I didn't realize the real question was about the DataGridView control.
Isn't this the same as setting the values directly:
this.tag1 = tags[0];
this.tag2 = tags[1];
this.tag3 = tags[2];
EDIT: as you sayd you don't know how many variables will be needed, then you need only one, and that is a list:
var list = new List<string>();
for (int i = 0; i < tags.Length; ++i)
{
list.add(tags[i]);
}
If all you want is to copy all values, you can even do this:
var list = new List<string>(tags);
Tell me whether this is what you want or not... maybe I have misunderstood the question.
The whole loop is pointless. But unless the tags array length is always going to be the same, you have to be sure not to go out of bounds...
if(tags.Length >= 1) this.tag1 = tags[0];
if(tags.Length >= 2) this.tag2 = tags[1];
if(tags.Length >= 3) this.tag3 = tags[2];
if(tags.Length >= 4) this.tag4 = tags[3];
if(tags.Length >= 5) this.tag5 = tags[4];
... so on for however many this.tag# you have.
This is essentially the same:
for(int index = 0; index < tags.Length[]; index++){
switch(index){
case 0:
tag1 = tags[0];
break;
// And so on
}
}

Programatically reference ascending variable names (var1, var2, ... )

I'm currently coding a project that can take up to 200 entries of a specific product, as determined by user input. Basically, my GUI loads, and I use jQuery to dynamically build the entries whenever there is a change to the amount field. When using jQuery, I simply give each of them ids in the form of variable1, variable2, ...., variableX (where X is the amount of entries indicated). Small snippet of code to clarify:
for(var i = 1;i <= amount_selected; i++) {
$('table_name tr:last').after('<tr><td><input type="text" id="variable' + i + '"></td></tr>');
}
Now when I try to move to the back end, I'm trying to reference these variable names by putting them in a list. I went ahead and put them in a list of HtmlInputText, to call the Variable names from the list itself. (This would save having to call all (up to 200) methods manually, which is really not an option).
So what I did (in C#) was:
List<HtmlInputText> listvar = new List<HtmlInputText>();
for(int i = 1; i <= amount_selected; i++) {
string j = "variable" + Convert.ToString(i);
HtmlInputText x = j;
listvar.Add((x));
samplemethod(listvar[i]);
}
But it's not working at all. Does anyone have any ideas as to how this would be done, without doing so manually? I know my logic might be completely off, but hopefully this illustrates at least what I'm attempting to do.
I'm assuming these inputs are in a form? If you're submitting then you can access the text boxes from the Request object:
List<string> results = new List<string>();
for (int i = 1; i <= amount_selected; i++)
{
string s = String.Format("{0}", Request.Form["variable" + Convert.ToString(i)]);
results.Add(s);
}
you could do $("#variable" + Convert.ToString(i)).val()

Categories