xamarin forms - changing button text on all carousel content pages - c#

What would be the "best" (or a better) way to do the following?
In a carousel page (say 6 content pages), I click a button, part of the action changes the text on that button, but it also has to change for all the other content pages.
I currently have this happening in the carousel pages OnCurrentPageChanged(), where I call a function and pass in "this". helpers.ChangeAll(this);
public void ChangeAll(CarouselSwipePage page)
{
foreach (SwipePageContent v in page.Children)
{
Button b = v.Content.FindByName<Button>("pause");
if (GlobalSettings.Settings.Default.CarouselCountEnabled) //this is set elsewhere and is used to determine whether the carousel is changing automatically, if it is then set the text to pause
{
b.Text = FontAwesomeFont.PauseCircleO;
}
else
{
b.Text = FontAwesomeFont.PlayCircleO;
}
}
}
This works ok on android but on ios when the user swipes to the next content page after clicking the button, the button text is momentarily the old value before changing to the new value, due to the function being called OnCurrentPageChanged().
Apart from that I'm sure there must be a better way to do this, it looks rubbish.

What about creating a style for the buttons, and just change the text value of the style?
So, using binding properties or dynamic resources, when you change the value, it is going to change all the buttons of your application that use this style. I think this approach is pretty much better and simpler than a loop.

Related

Mudblazor dialog box is reseting a form when you click on a non form area

I'm using a MudDialog that takes in an Id and creates an edit form from a component. When I click on any of the white space around the edit form or even between any of the form fields then the form resets. (For some reason the note field doesn't reset). The dialog box is functioning and updates the database when you hit the submit button, but this experience of easily resetting every field is not making a good user experience.
`<MudButton ButtonType="ButtonType.Button" #onclick="#((e) => EditDeliverableDialog(context))" Variant="Variant.Filled" Color="Color.Info" Class="ml-auto" Size="Size.Small" StartIcon="#Icons.Outlined.Edit">Edit</MudButton>`
`async Task EditDeliverableDialog(DeliverableDto deliverable)
{
var parameters = new DialogParameters { ["DeliverableId"] = deliverable.DeliverableId.ToString() };
var options = new DialogOptions() { Position = DialogPosition.Center, CloseButton = true, MaxWidth = MaxWidth.Large };
var dialog = DialogService.Show<DeliverableDialog>("Edit Deliverable", parameters, options);
var result = await dialog.Result;
}`
`<MudDialog >
<DialogContent>
<ContentWrapper>
<AlertMessage #ref="_alert" />
#if (deliverableIdAsInt == 0)
{
<p>Loading table for the deliverable...</p>
}
else
{
<SingleDeliverableTable ButtonColor="Color.Primary" IsTitleShown="false" Context=context ButtonVerb="Save" EditedDeliverable=editedDeliverable DeliverableDto=deliverableDto IsDisabled="false" OnValidSubmitForReal=OnValidSubmit SingleDeliverableId=deliverableIdAsInt></SingleDeliverableTable>
}
</ContentWrapper>
</DialogContent>
</MudDialog>`
This is before clicking anything
This is after clicking
I've tried changing some of the dialog options: disable back drop dialog, changing the width of the dialog, position.
I've looked for anything that could cause the form to reset. I've used the exact same edit component without a dialog box and it doesn't reset any of the fields. When the fields reset I edited every field and the form is still using the id of the item I clicked on.
With more testing on the edit component form, I noticed where if you go to the form and resize the page then this resets each of the fields as well.
Hy Stephen! Thank you for sharing your problem! I'm facing the same problem! If I change a MudTextField and click in the text of a checkbox the problem happens too. Not only out of the form area. I noticed that the dialog reload in this situation (clicking out of the form), then I made a workaround. You need to use a nullable DTO variable and copy the Parameter during OnParametersSet:
[Parameter]
public DeliverableDtoType DeliverableDto {get; set;}
private DeliverableDtoType? _model;
protected override async Task OnParametersSetAsync()
{
if (_model is null)
_model = DeliverableDto;
}
With this code, when the dialog reload, the model will not change.
Found out the problem was the edit form was actually being called twice with the single deliverable table form. First call would come up with the correct data from DTO and the second call was resetting the data sent from DTO.
In blazor if you click, on something that is a part of your view, you most likely are triggering the equivalent of a StateHasChanged within the component.
I think the problem you are facing is that you haven't bound the values of those inputs to a model using the #bind-Value syntax. Meaning that when you've added values to your inputs, then clicked, those values weren't saved onto your model and when the redraw occured you've lost your state, as the redraw draws based on the model.
An example of this would be like this (using a sub component from mudblazor):
<MudTextField T="string" Text="#_model.Name" Label="Name" Required="true" For="()=>_model.Name"></MudTextField>
In the above, the text field will be rendered with whatever value is in th emodel, if you modify this text field it's not updating the model, just the UI. So if a UI refresh is triggered the text field will update back to what it was which is probably blank in your case.
<MudTextField T="string" #bind-Text="#_model.Name" Label="Name" Required="true" For="()=>_model.Name"></MudTextField>
adding the #bind- to the Text will make sure that when the value in the text field is changed, the model is also updated.

How can I open page in my Xamarin app without using navigation?

I have a Xamarin Forms application, which has 2 buttons on the toolbar. Currently I'm using FreshMVVM (and it's navigation). I want to load pages without putting them into the navigation. I do not want to have the 'back' button on the toolbar, also I do not want the user return the last page.
Here's how I push a page currently:
CoreMethods.PushPageModel<FirstChoicePageModel>();
I tried to push as a modal, but that way the toolbar buttons does not work until I press back. Should I make new navigation containers and switch to them if I push the buttons?
It's been a little while since I've used FreshMVVM, but if I recall correctly, you have 2 options:
If you want to completly reset the nav stack, you can do CoreMethods.PushPageModelWithNewNavigation<FirstChoicePageModel>();
If you want to keep the nav stack, you can set NavigationPage.SetHasBackButton(this, false); in the code behind of the view.
For both of these options, it may necessary to intercept the back button on Android. In the code behind there is an overrideable method:
protected override bool OnBackButtonPressed()
{
return true; // prevent Xamarin.Forms from processing back button
}
If you want to show a page, but you doesn't want to navigate (change the current page), you can always use Popups.
See this link https://github.com/rotorgames/Rg.Plugins.Popup

WPF application in one window

I am new in WPF and want to create WPF application like cookbook. I already done this and app work correctly. But I make it in this way:
First screen show buttons, which open new windows to do something. As a result i have 14 different windows. It is ok, but now i want to make it in other way.
I am trying to make one window, which will be showed at start, and change content. I divided window on two grids. First is static and is placed on bottom. It contains buttons, which represents functionality of the program. Second one will be dynamic. There i want to show content of every window. So i want to change content of this panel instead of creating new windows.
I tried to make *.cs files which will create controls in code-behind, functions and data. But my idea is not succesful and i do not know how to do this.
At all, I want to create app, which will work like this:
- if you click button "Add receip" then app will show controls to add name, ingredients and save it at the end.
- if you clik "Show receip" previous content will be replaced by list of ingredients
and etc.
I hope you will understand me.
You can create a Frame instead of second grid. Frame allows you to show pages, and not in seperate windows, in Frame itself. You can navigate the frame into the page like
mainFrame.Source = new Uri("Page1.xaml",UriKind.Relative);
This changes the frame to your page. You can change the source again, if you wanna change the page again.
Note: You can add tags to your buttons like "showReceip" and you can make just one buttonclick event for your buttons. Code will look like this.
mainFrame.Source = new Uri((sender as Button).Tag.ToString() + ".xaml",UriKind.Relative);
That takes the tag of your clicked button, add the string ".xaml" on it and take it on the source part. So, if your tag is "Page1", Source will look like "Page1.xaml" as my solution.
Appreciate the try, I hope you are looking for WPF user controls instead for separate windows. User controls are similar to windows you can create the UI and functionalities in the user control. I would like to recommend you to design the main window like the following:
<Grid>
<Canvas Name="canFunctionalButtons">
<!--Define the buttons inside this canvas
And allocate proper place for this in the UI
-->
</Canvas>
<Canvas Name="canControlContainer">
<!--This is to display the user control
Which can be changed dynamically according to the Button's click
-->
</Canvas>
</Grid>
Then you have to add click event for those buttons, which will add specific user control to the canControlContainer canvas. An example for adding an user control to this canvas is as follows, Let btnAddSomething be a button and btnAddSomething_Click be its click event then you can do something like:
private void btnAddSomething_Click(object sender, RoutedEventArgs e)
{
canControlContainer.Children.Clear(); // will remove previous contols from this canvas
// UC_AddSomething be the user control that you wanted to add here
canControlContainer.Children.Add(new UC_AddSomething());
}

Hide elements in a web page whilst using a web-browser control for WP7

I am currently working on an app for WP7 for my university, and need a temporary solution to a problem. Now this solution is, that I will be loading a webpage using the web browser control for WP7. For example: http://m.iastate.edu/laundry/
Now as you see on the webpage, there are certain elements I want to hide, for example the back button. For now, what I have done to handle the back button is something like this:
private void webBrowser1_Navigating(object sender, NavigatingEventArgs e)
{
// Handle loading animations
// Handle what happens when the "back" button is pressed
Uri home = new Uri("http://m.iastate.edu/");
// The the current loading address is home
// Cancel the navigation, and go back to the
// apps home page.
if (e.Uri.Equals(home))
{
e.Cancel = true;
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}
}
Now that works beautifully, except for the part that there is a back button on the hardware.
So my second option is to completely hide the back button ONLY on that page, and not its children. So not on http://m.iastate.edu/laundry/l/0
I am still debating on just parsing the data and displaying it in my own style, but I'm not sure if that's completely needed seeing how the data needs constant internet service and is already in a well-put format. Plus, I feel like that would be a waste of resources? Throw in your opinions on that too :)
Thanks!
You should inject a script in the page with InvokeScript.
Here is the kind of Javascript code you need to remove the back button:
// get the first child element of the header
var backButton = document.getElementsByTagName("header")[0].firstChild;
// check if it looks like a back button
if(backButton && backButton.innerText == "Back") {
// it looks like a back button, remove it
document.getElementsByTagName("header")[0].removeChild[backButton];
}
Call this script with InvokeScript:
webBrowser1.InvokeScript("eval", "(function() { "+ script +"}()");
Warning: IsScriptEnabled must be set to true on the web control
If the removal of the back button depends of the page, just test the navigating URI in C# and inject the script if neeeded.

Button Questions in MonoTouch

I'm working with MonoTouch and I have come up with three questions around buttons that I'm hoping someone can help me with.
I'm trying to change the "Back" button in the title bar. How do I do this? I've seen the thread posted here: How to change text on a back button. However, that doesn't work. I get the vibe that I'm not accessing the controller property. Currently, I receive a NullReferenceException when I attempt to set the button text in the ViewDidLoad method. Currently, I'm trying to set the text like such:
this.NavigationItem.BackBarButtonItem.Title = "Back";
I have the suspicion that I'm not accessing the root controller, but I'm not sure how to do this.
For a "back" button on a separate page, I want to perform a custom action. I want it to go back like it does. But before that happens, I want to execute some custom code. How do I do this?
I need to create something that looks like a hyperlink within a paragraph of text. How do I do that?
MonoTouch seems cool. However, the learning curve is a bit steeper than I had anticipated. Thank you!
For your first question the MonoTouch-specific answer (to the question you provided) works perfectly.
this.NavigationItem.BackBarButtonItem = new UIBarButtonItem ("MyBack", UIBarButtonItemStyle.Plain, null);
Make sure to the all the answers. This code needs to be called in the pushing controller, not the controller being pushed.
UPDATE
For your second question you likely noticed a few overloads that takes a Selector or a delegate. However they won't work for a Back button.
One way to work around this iOS limitation is to override ViewDidAppear or ViewDidDisappear to get similar notification.
I solved your third question by creating a custom button in de viewbuilder. Setting the type to custom removes de standard borders and makes it look like a line of text. Simply change its size and style it to make it look more like an hyperlink. I left an empty space in my text and and put my custom button in that space.
I created an extension method that allows you to change the back button text and optionally handle the TouchUp action with your own code. It also keeps the same border look as the default back button.
public static class MyExtensions
{
public static void SetCustomBackButton(this UIViewController uiViewController, string buttonText, Action onClick)
{
uiViewController.NavigationItem.HidesBackButton = true;
var dummyButton = UIButton.FromType (UIButtonType.Custom);
var backButton = (UIButton)MonoTouch.ObjCRuntime.Runtime.GetNSObject (
MonoTouch.ObjCRuntime.Messaging.IntPtr_objc_msgSend_int (
dummyButton.ClassHandle, MonoTouch.ObjCRuntime.Selector.GetHandle ("buttonWithType:"), 101));
backButton.SetTitle (buttonText, UIControlState.Normal);
backButton.TouchUpInside += delegate {
if (onClick != null)
onClick ();
else
uiViewController.NavigationController.PopViewControllerAnimated (true);
};
uiViewController.NavigationItem.LeftBarButtonItem = new UIBarButtonItem (backButton);
}
}

Categories