Xamarin Forms prevent iOS clearing previous entry text after focus - ios

In Xamarin Forms I tried to add show password feature to entry. so I toggled isPassword(true/false).
user has to click on the eye icon to see the password and it means that entry will lose focus.
Now, In iOs if user touches entry to enter more character or delete some. iOs will clear the entry and user has to enter again.
Is there a way to disable this?

We can Custom EntryRenderer to avoid that . Such as creating a CustomEntryRenderer in project.iOS solution :
[assembly: ExportRenderer(typeof(Entry), typeof(CustomEntryRenderer))]
namespace AppEntryTest.iOS
{
public class CustomEntryRenderer : EntryRenderer,IUITextFieldDelegate
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control.SecureTextEntry)
{
Control.Delegate = new MyTextFiledDelegate();
}
}
}
internal class MyTextFiledDelegate : UITextFieldDelegate
{
public override bool ShouldChangeCharacters(UITextField textField, NSRange range, string replacementString)
{
//return base.ShouldChangeCharacters(textField, range, replacementString);
string updatedString = textField.Text.Substring(0, (int)range.Location)+replacementString+textField.Text.Substring((int)(range.Location+range.Length));
textField.Text = updatedString;
return false;
}
}
}
Used in Xaml :
<StackLayout VerticalOptions="FillAndExpand" Padding="20">
<Entry Text="First Entry" IsPassword="True"/>
<Entry Placeholder="Second Entry"/>
</StackLayout>
The effect :

Related

Xamarin Forms RefreshView stopped working randomly

Can someone please tell me what I'm doing wrong? The RefreshView was just working yesterday and today I can't get it to work in any page. I created a brand new page with just a RefreshView and when I try to pull down it doesn't budge. Doesn't pull down, doesn't refresh, nothing. It was just working last night and today after no code changes it's not working. I've tried on the simulator and on my actual iPad. Before anyone suggests, there are no updates to any of my NuGet packages and I can't find any reference to this issue on Google.
XF: v5.0.0.2244
View:
<?xml version="1.0" encoding="utf-8" ?>
<views:MvxContentPage
x:Class="MyApp.UI.Pages.PricingPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:MyApp.Core.ViewModels;assembly=MyApp.Core"
xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
Title="{Binding Title}"
x:DataType="viewModels:PricingViewModel"
x:TypeArguments="viewModels:PricingViewModel">
<views:MvxContentPage.Content>
<RefreshView Command="{Binding RefreshCommand}" IsRefreshing="{Binding IsRefreshing}">
<CollectionView ItemsSource="{Binding MenuItems}" />
</RefreshView>
</views:MvxContentPage.Content>
</views:MvxContentPage>
ViewModel:
using System.Threading;
using System.Threading.Tasks;
using MyApp.Core.ChurromigosApi;
using MyApp.Core.Services;
using MyApp.Core.ViewModels.Base;
using MvvmCross.Commands;
using MvvmCross.ViewModels;
namespace MyApp.Core.ViewModels
{
public class PricingViewModel : BaseViewModel
{
private readonly IMenuItemService menuItemService;
public PricingViewModel(IMenuItemService menuItemService)
{
this.menuItemService = menuItemService;
this.RefreshCommand = new MvxAsyncCommand(this.Refresh);
this.MenuItems = new MvxObservableCollection<MenuItem>();
this.Title = "Pricing";
}
public MvxObservableCollection<MenuItem> MenuItems { get; set; }
public IMvxAsyncCommand RefreshCommand { get; }
public bool IsRefreshing { get; set; }
public override Task Initialize()
{
this.IsRefreshing = true;
return Task.CompletedTask;
}
private async Task Refresh()
{
var allMenuItems = await this.menuItemService.GetMenuItems(CancellationToken.None);
this.MenuItems.Clear();
this.MenuItems.AddRange(allMenuItems);
}
}
}
I found a similar problem with RefreshView, though in my case instead of becoming unresponsive, the app just crashes.
It appears that we need to pay more attention to the binding Mode for the property used for the IsRefreshing indicator:
If we want the RefreshView to automatically trigger the command when the VM's binded property is changed to True, then don't include a Mode, or use Mode=TwoWay, but don't manually change the value or you'll be stuck in a loop (or include a if(IsRefreshing) return; in your command or you wont get any results)
If we want to manually set the VM's property in the backend to show/hide the IsRefreshing activity indicator without triggering the command, then use Mode=OneWay or else you will be stuck in a loop.
In your particular case it could be related to the fact that you're setting your IsRefreshing property to true, and then you never set it back to false? I would wrap your Refreshing() method's code with a try, setting IsRefreshing=false at the beginning and then =false in a finally block.

MVVM Light TextView two-way binding in Xamarin (Android)

Has anyone successfully implemented a two-way binding on a TextView with MVVM Light? Two-way works perfectly fine with EditView, but the moment I try two-way binding with TextView - only one way binding works. Does anyone have any insight as to why, please?
View Model:
private string _someField;
public string SomeField
{
get { return _someField; }
set { Set(ref _someField, value); }
}
View:
private EditText _editableText;
public EditText EditableText;
{
get { return _editableTex ?? (_editableTex = FindViewById<EditText>(Resource.Id.editText1)); }
}
private TextView _simpleText
public TextView SimpleText
{
get { return _simpleText ?? (_simpleText = FindViewById<TextView>(Resource.Id.textDateDisplay)); }
}
protected override void OnCreate(Bundle savedInstanceState)
{
bindings.Add(this.SetBinding(() => vm.SomeField, () => EditableText.Text, BindingMode.TwoWay));
bindings.Add(this.SetBinding(() => vm.SomeField, () => SimpleText.Text, BindingMode.TwoWay));
}
No errors are thrown. But when I change (in code) of the View the text of the EditableText (EditableText.Text="asdf";) the corresponding set { Set(ref _someField, value); } triggers in the VewModel. It also triggers, naturally, if I just type in the EditText widget.
However, when I change (in code) the text property of the SimpleText (SimpleText.Text="2145";) it does not trigger the corresponding set.
Does anyone know why?
Thank you very much for help,
mike
You can't set a two-way binding with TextViews, because they doesn't allow input by user.
When you are using MVVM pattern you should never update the view. You should update the bound model property. So you should replace SimpleText.Text = "2145"; with vm.SomeField = "2145";.

How to create view's actions listener for MvxItemTemplate

I have a view which contains an MvxListView and a form. I can hide the softkeyboard using the following code in my view's code (as this is pure view concerns)
var editText = FindViewById<EditText>(Resource.Id.newCheckbookName);
editText.EditorAction += (object sender, TextView.EditorActionEventArgs e) =>
{
if (e.ActionId == ImeAction.Done)
{
InputMethodManager inputMgr = GetSystemService(InputMethodService) as InputMethodManager;
inputMgr.HideSoftInputFromWindow(CurrentFocus.WindowToken, 0);
}
return;
};
In my item template I have an other text editor and would like to have the same behavior. But where can I add my code as I don't have any view code for the MwxItemTemplate ?
I think the easy way to do this is to use a custom 'View' within the listitem.
Note: that 'View' here refers to Android Views - not Model-View-ViewModel views - sorry for the naming confusion!
Creating custom views is easy to do...
Just create a custom View - e.g.
namespace Angevelle.App1.UI.Droid.Controls
{
public class MyText : EditText
{
public MyText(Context context, IAttributeSet attrs)
: base(context, attrs)
{
this.EditorAction += OnEditorAction;
}
private void OnEditorAction(object sender, EditorActionEventArgs editorActionEventArgs)
{
if (editorActionEventArgs.ActionId == ImeAction.Done)
{
// this code not tested - but something like this should work
var imm = (InputMethodManager)Context.GetSystemService(Context.InputMethodService);
imm.HideSoftInputFromWindow(WindowToken, 0);
}
}
}
}
Then you can use that View in your AXML just as you do Android or Mvx views:
<angevelle.app1.ui.droid.controls.MyText
android:layout_height=....
/>
If you are finding angevelle.app1.ui.droid.controls too verbose, then you could shorten this using an abbreviation in setup.cs:
protected override IDictionary<string, string> ViewNamespaceAbbreviations
{
get
{
var abbreviations = base.ViewNamespaceAbbreviations;
abbreviations["Abv"] = "angevelle.app1.ui.droid.controls";
return abbreviations;
}
}
then you can just use:
<Abv.MyText
android:layout_height=....
/>
An alternative approach might be to somehow customise the list...
If you ever do need to completely customise a listview and its adapter, then this can be easily done using the same type of technique - inherit from MvxBindableListView in your UI project:
public class MyListView : MvxBindableListView
{
public MyListView(Context context, IAttributeSet attrs);
: base(context, attrs, new MyListAdapter(context))
{
}
}
where MyListAdapter overrides the view creation:
public class MyListAdapter : MvxBindableListAdapter
{
public MyListAdapter(Context context)
: base(context)
{
}
// put your custom Adapter code here... e.g.:
protected override MvxBindableListItemView CreateBindableView(object source, int templateId)
{
return new MySpecialListItemView(_context, _bindingActivity, templateId, source);
}
}
where MySpecialListItemView inherits from MvxBindableListItemView but adds your own custom features.
Using this approach your list would then change from:
<Mvx.MvxBindableListView
....
/>
to:
<Abv.MyListView
....
/>
For more examples of custom views, take a look around GitHub - e.g. at some of the Calendar, ColorPicker, ActionBar projects in https://github.com/Cheesebaron
Don't expect your custom controls to render in the xamarin designer (well, not yet...)
Two final notes...
To reuse code... you might want to put that HideSoftInputFromWindow functionality in an extension method somehow so that you can just call anyEditText.HideOnDone()
Be careful when using the Monodroid/monotouch events on Views/UIViews - these events tend to use the native delegates/listeners - and so sometimes you can find that attaching something to subscribe to one event can unattach something else! Generally you are OK as long as you don't mix and match the C# event subscriptions at the same time as the native listener/delegate handlers.

Umbraco: Determining Who Last Updated Content

I see in the API there is a way to grab the UpdateDate field. Is there a way to determine WHO made the last update to a particular content node? In other words, the user ID of the person that last edited a particular node?
Here's some of the code I'm attempting to use:
Document[] releaseDocs = Document.GetRootDocuments();
User currentUser = User.GetCurrent();
foreach (var doc in releaseDocs)
{
docPermissions = currentUser.GetPermissions(doc.Path);
if ((docPermissions.Contains("F")) && (docPermissions.Contains("U")))
{
if (doc.HasPendingChanges())
{
if (doc.ParentId > -1)
{
lblPageContent += doc.Writer.Name;
}
}
}
}
I did some more research on this and, while writerID and writerName are supposed to store the last editor, there appears to be a bug in Umbraco. Their support suggested creating a hidden field that updates with the editor user data, so that's my temporary work around for now.
You could try writerName and writerID same way you use UpdateDate like as below:
if you are using Razor you can use as below:
#Model.writerName
#Model.writerID
in XSLT:
<xsl:value-of select="$currentpage/#writerName" />
<xsl:value-of select="$currentpage/#writerID" />
in C# Usercontrol:
using System;
using umbraco.NodeFactory;
namespace UmbracoTestingProj
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Node node = Node.GetCurrent();
int writerId = node.WriterID;
string wrtierName = node.WriterName;
}
}
}
I hope this would help,
if you have question just just comment below

C# .net windows application - Printing Text Box Values

I have two text boxes when i input in these text boxes , by clicking the print button , it should directly printed with the connected printer. can anybody help me how should i do this?
The example below is a basic idea of using/inheriting the PrintDocument class:
using System.Drawing.Printing;
public class PrintDoc : PrintDocument
{
// there are other properties you can enter here
// for instance, page orientation, size, font, etc.
private string textout;
public string PrintText
{
get { return textout; }
set { textout = value; }
}
// you will also need to add any appropriate class ctor
// experiment with the PrintDocument class to learn more
}
Then from your form's button event, call something like:
public void PrintDocument()
{
//instance PrintDocument class
PrintDoc printer = new PrintDoc();
//set PrintText
printer.PrintText = myTextBox.Text;
printer.Print(); // very straightforward
}

Resources