How do I access the code block within a Blazor RenderFragment? - c#

I'm new to programming, C# Blazor, and RenderFragments in general, so forgive me if this is a basic question.
I need to set up a tabbed dialog interface where different tabs appear based on which menu buttons are clicked. I set up a DevExpress menu item which appears as a button:
<DxMenuItem Text="States" IconCssClass="homeMenuButtonStates" CssClass="menuItemSm" Click="OnStatesBrowseClick" />
When the user clicks it, the OnStatesBrowseClick function is called:
public void OnStatesBrowseClick()
{
tabName[tdiIndex] = "States";
TdiNewTab(tabName[tdiIndex]);
}
As you can see, its job is to assign a value to a member of a string array (tdiIndex was assigned "0"), and call the TdiNewTab method with argument tabName[tdiIndex] which evaluates to "States."
TdiNewTab has a switch statement which, for now, only has a case for "States."
public void TdiNewTab(string switchTabName) {
switch (switchTabName)
{
case "States":
renderStatesBrowsePage(tdiIndex);
break;
}
tdiIndex++;
}
In the event that "States" comes up, it points to renderStatesBrowsePage which should create a tab.
private RenderFragment renderStatesBrowsePage(int index)
{
deleteMe++;
RenderFragment item = tabsChildContent =>
{
deleteMe++;
tabsChildContent.OpenComponent<DxTabPage>(0);
tabsChildContent.AddAttribute(2, "Text", $"Tab # {index}");
tabsChildContent.AddAttribute(3, "ChildContent", (RenderFragment)((tabPageChildContent) =>
{
tabPageChildContent.OpenComponent<States>(0);
tabPageChildContent.CloseComponent();
}));
tabsChildContent.CloseComponent();
};
return item;
}
However, nothing happens. Using breakpoints, I determined that the block within "RenderFragment item = tabsChildContent =>" does not get executed. Indeed, when I put both "deleteMe++"s in there, only the first one incremented the variable.
I'm at a loss as to why the block won't execute. Any advice would be much appreciated!
In response to answer from Mister Magoo:
I'm now trying to call the RenderFragment from within my markup:
<DxMenuItem Text="States" IconCssClass="homeMenuButtonStates" CssClass="menuItemSm" Click="StatesBrowseClick">
#if (statesBrowse == 1)
{
#renderStatesBrowsePage(0);
}
</DxMenuItem>
#code
public void StatesBrowseClick()
{
int statesBrowse = 1;
}
However, nothing still happens. I made sure statesBrowse, which was initialized to "0" outside of the method, equaled 1 after the click. I also tried removing the #if statement (leaving just "#renderStatesBrowsePage(0);", and I got the same result.
Note: I'm using VS 2019, and in StatesBrowseClick, it tells me that "The variable 'statesBrowse' is assigned, but its value is never used." This seems inconsequential, though, as I have tried manually setting it to "1" and removing the "if" statement.

The block won't execute because there is nothing executing it.
renderStatesBrowsePage returns a RenderFragment that needs to be rendered - but you are discarding it here:
public void TdiNewTab(string switchTabName) {
switch (switchTabName)
{
case "States":
// This returns a RenderFragment but you are discarding it
renderStatesBrowsePage(tdiIndex);
break;
}
tdiIndex++;
}
It is hard to tell you what you should be doing without seeing more of your project, but generally a RenderFragment is rendered by adding it to the component markup
<div>some stuff</div>
<div>
#MyRenderFragment
</div>

Related

With server side Blazor, how do I get a function to fire when a variable is changed?

I feel like this is a simple question but I cannot find the answer. I want a function to fire after a variable is changed in a server side Blazor application.
I am using a Mud Blazor MudMenu. This is an example of the code if it matters:
<MudMenu>
<MudMenuItem #onclick="#(e => listValue= 1)">1</MudMenuItem>
<MudMenuItem #onclick="#(e => listValue= 2)">2</MudMenuItem>
</MudMenu>
This is the variable in a #code block if it matters:
public int listValue;
My variable listValue does change when I select the appropriate item. I have a function that takes this value and makes an api call. How do I trigger that function when the variable changes?
You can do more things in the delegate you passed to OnClick:
MudMenuItem OnClick="ea => { listValue = 1; apiClient.DoSomething(listValue+1); }">...
Or declare a method that takes a MouseEventArgs:
MudMenuItem OnClick="DoThing">...
#code{
void DoThing(MouseEventArgs ea){
listValue = 1;
apiClient.DoSomething(listValue+1);
}
}
Or declare a method with some other signature and giving a wrapping delegate that calls it:
MudMenuItem OnClick="_=>DoThing()">...
#code{
void DoThing(){
listValue = 1;
apiClient.DoSomething(listValue+1);
}
}
MudMenuItem OnClick="_=>DoThing(listValue=1)">...
#code{
void DoThing(int x){
apiClient.DoSomething(x+1);
}
}
That lattermost variation uses the fact that an assignment in C# returns the value that was assigned, which is then passed as the argument to the method- it's unusual, but legal.. I put it in more as a 'this is all just normal, legal C# method calling like any other syntax you can come up with
Or any other variation on the theme you can think of..

Trouble getting StateHasChanged to update an #if Statement

So I'm having trouble getting my Razor page to update an if statement.
The idea is when a user selects a button, it'll recount the string looking for how many of X values there are, right now we are looking for spaces. If theres one space, I want the input field locked (the user has no reason edit it). If theres more than one space, its unlocked.
Below is the if statement holding the tags
#if (NumOfSelectedValue <= 1)
{
<input class="form-control-sm" value="1" style="width: 40px" disabled />
}
else if (NumOfSelectedValue > 1)
{
<input class="form-control-sm" value="#NumOfSelectedValue" style="width: 40px" />
}
And here is the logic on how I thought it would be updated.
public void SpaceSelected() //ive used "async task"
{
int NumOfSelectedValue = SelectedCell.Count(x => x == ' ');//counting how many spaces there are with Linq
Console.WriteLine(NumOfSelectedValue);//post num of spaces in the console
//other versions ive used
//StateHasChanged();//update the if statement
//await InvokeAsync(StateHasChanged);
InvokeAsync(StateHasChanged);
}
Per your comments, you have a public property named NumOfSelectedValue. This is separate from the local variable NumOfSelectedValue you defined in SpaceSelected. Your solution is to not declare that local variable and instead just update the property:
public void SpaceSelected()
{
NumOfSelectedValue = SelectedCell.Count(x => x == ' ');
StateHasChanged(); // Probably not necessary unless you're calling this method in the background
}
Notice that we no longer have the int part in front of the assignment, which is what was declaring the variable.

I want to select dropdown element

I want to click a dropdown element. I have mentioned element's xpath/css both. But it is constantly giving error "no element found". I am working on C# on selenium . I have also given dropdown ID first then wait for the dropdown element and then get it clicked but it gives same error always. Any idea ???
It depend of available iFrame or maybe you should switch to default content. It's complicated, without your code.
Any way try this code. It's working for me:
private static void ChooseZipCode(IWebDriver wd)
{
if (!wd.FindElement(By.XPath("//td[#id='divShipStateCombo']/select//option[3]")).Selected)
{
wd.FindElement(By.XPath("//td[#id='divShipStateCombo']/select//option[3]")).Click();
}
}
// where is "[3]" the position your element(ID) in drop down menu
// or
private static void SelectElement(IWebDriver wd, string CardType)
{
SelectElement cardSelect = newSelectElement(wd.FindElement(By.Name("CardType")));
cardSelect.SelectByText("Visa Card");
}

Why does the VS2005 debugger not report "base." values properly? (was "Why is this if statement failing?")

I'm working on an existing class that is two steps derived from System.Windows.Forms.Combo box.
The class overrides the Text property thus:
public override string Text
{
get
{
return this.AccessibilityObject.Value;
}
set
{
if (base.Text != value)
{
base.Text = value;
}
}
}
The reason given for that "get" is this MS bug: http://support.microsoft.com/kb/814346
However, I'm more interested in the fact that the "if" doesn't work.
There are times where "base.Text != value" is true and yet pressing F10 steps straight to the closing } of the "set" and the Text property is not changed.
I've seen this both by just checking values in the debugger, and putting a conditional breakpoint on that only breaks when the "if" statement's predicate is true.
How on earth can "if" go wrong?
The class between this and ComboBox doesn't touch the Text property. The bug above shouldn't really be affecting anything - it says it's fixed in VS2005. Is the debugger showing different values than the program itself sees?
Update
I think I've found what is happening here.
The debugger is reporting value incorrectly (including evaluating conditional breakpoints incorrectly). To see this, try the following pair of classes:
class MyBase
{
virtual public string Text
{
get
{
return "BaseText";
}
}
}
class MyDerived : MyBase
{
public override string Text
{
get
{
string test = base.Text;
return "DerivedText";
}
}
}
Put a breakpoint on the last return statement, then run the code and access that property.
In my VS2005, hovering over base.Text gives the value "DerivedText", but the variable test has been correctly set to "BaseText".
So, new question: why does the debugger not handle base properly, and how can I get it to?
Use String.Compare for comparing strings. There are subtleties with strings. I cannot tell you why the if would fail, other than that your strings might not really be 'equal'
... and this just about wraps up my new question. Ah well.

WPF Binding issue with updating values

I have a .xaml file and a .cs file that share value with Binding.
To make it simples, I have 1 button and 1 textbox. I want to button to be disabled when the textbox's text has no character.
Here is the two codes of the xaml for binding:
<TextBox Name="txtSend" Text="{Binding Path=CurrentText,UpdateSourceTrigger=PropertyChanged}"></TextBox>
<Button IsEnabled="{Binding Path=IsTextValid}" Name="btnSend">Send</Button>
The two properties in the .cs file look like that:
public string CurrentText
{
get
{
return this.currentText;
}
set
{
this.currentText = value;
this.PropertyChange("CurrentText");
this.PropertyChange("IsTextValid");
}
}
public bool IsTextValid
{
get
{
return this.CurrentText.Length > 0;
}
}
The this.PropertyChanged is simply a method that call PropertyChanged from INotifyPropertyChanged.
The problem is that I have to call the this.PropertyChange("IsTextValid"); in the Setter of the CurrentText to be able to have the button state change.
Question 1) Is it the good way to do it... if the rules become more complexe I might require to call a lot of PropertyChanged...?
Question 2) My button is enable when the form load. How can I make it check the method from the start?
Question 1: This is correct. There is no problem doing that. However you could take a look at the validation using the IDataErrorInfo. (Google search for it, and you will find a lot of good examples)
Question 2: make sure your "currentText" string is initialized with string.empty. Because if you did not initialized it, it will be null, and the getter for IsTextValid will throw an exception, and WPF will fail to retrieve the value.
Or do it like that:
public bool IsTextValid
{
get
{
return ! string.IsNullOrEmpty( this.CurrentText );
}
}
Your way of doing it is correct. If you are a bit lazy (as I am), you should have a look on the NuGet package Fody.PropertyChanged.
Your code would simplify to
public string CurrentText { get; set; }
public bool IsTextValid { get { return this.CurrentText.Length > 0; } }
Fody.PropertyChanged does the rest for you. It automatically adds the needed instructions to notify that CurrentText changed, and it even detects that IsTextValid depends on CurrentText and notifies for it, too.

Categories