Xamarin.Forms refresh TextProperty of Editor - data-binding

Is there a way to change the text in an Editor cell after an event?
I have an Editor cell that shows an address from an SQLite database. I also have a button that gets the current address and shows this in an alert that asks if they would like to update the address to this. If Yes, then I would like to show the new address in the Editor cell.
public class UserInfo : INotifyPropertyChanged
{
public string address;
public string Address
{
get { return address; }
set
{
if (value.Equals(address, StringComparison.Ordinal))
{
return;
}
address = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
My code for the editor cell is
Editor userAddress = new Editor
{
BindingContext = uInfo, // have also tried uInfo.Address here
Text = uInfo.Address,
Keyboard = Keyboard.Text,
};
and then this after it has got the current address I have this
bool response = await DisplayAlert("Current Address", "Would you like to use this as your address?\n" + currAddress, "No", "Yes");
if (response)
{
//we will update the editor to show the current address
uInfo.Address = currAddress;
}
How do I get it to update the Editor cell to show the new address?

You are setting the BindingContext of the control, but not specifying a binding to go with it. You want to bind the TextProperty of the Editor to the Address property of your context.
Editor userAddress = new Editor
{
BindingContext = uinfo,
Keyboard = Keyboard.Text
};
// bind the TextProperty of the Editor to the Address property of your context
userAddress.SetBinding (Editor.TextProperty, "Address");
This may also work, but I'm not positive the syntax is correct:
Editor userAddress = new Editor
{
BindingContext = uinfo,
Text = new Binding("Address"),
Keyboard = Keyboard.Text
};

Related

Xaramin form -calling variable from other .cs file

I am doing a quiz game in Xaramin. forms. and for the score function. if the user got a correct answer, I want the score will add 1.but in my case even the give the correct answer, the score is not adding.
I am also trying to bind to the "score" variable to a label. I want to know if i put a correct code or not.
Button
private void submit_Clicked(object sender, EventArgs e)
{
string answer = this.answer.Text;
string canswer = "correct";
if (answer != null)
{
string ranswer = answer.Replace(" ", string.Empty);
if (ranswer.ToLower() == canswer)
{
DisplayAlert("GoodJob", "You got the correct answer", "OK");
bindingModel b = new bindingModel();
b.score++;
(sender as Button).IsEnabled = false;
}
else
{
DisplayAlert("Unfortunately", "Your answer is wrong", "OK");
(sender as Button).IsEnabled = false;
}
}
}
ViewModel
public class bindingModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int displayScore => Score;
public int score = 0;
void OnPropertyChanged(int score)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(score.ToString()));
}
public int Score
{
get => score;
set
{
if (score != value)
{
score = value;
OnPropertyChanged(score);
}
}
}
}
Model
<Label Text="{Binding Score}"/>
in your page constructor, keep a reference to your VM
bindingModel VM;
// this is your constructor, the name will match your page name
public MyPage()
{
InitializeComponent();
this.BindingContext = VM = new bindingModel();
...
}
then in your event handler, you do NOT need to create a new bindingModel
// update the Count on the VM
VM.Count++;
Answer
There's two things broken here:
You are re-initializing your ViewModel instead of referencing the same instance
You are passing the wrong value into PropertyChangedEventArgs
1. Referencing the View Model
You are re-initializing the ViewModel every time by calling bindingModel b = new bindingModel();
Lets initialize the ViewModel once, store it as a field, set it as the BindingContext for our ContentPage, and reference that field in submit_Clicked
public partial class QuizPage : ContentPage
{
readonly bindingModel _bindingModel;
public QuizPage()
{
_bindingModel = new bindingModel();
BindingContext = _bindingModel;
}
private async void submit_Clicked(object sender, EventArgs e)
{
string answer = this.answer.Text;
string canswer = "correct";
Button button = (Button)sender;
if (answer != null)
{
string ranswer = answer.Replace(" ", string.Empty);
if (ranswer.ToLower() == canswer)
{
await DisplayAlert("GoodJob", "You got the correct answer", "OK");
_bindingModel.score++;
button.IsEnabled = false;
}
else
{
await DisplayAlert("Unfortunately", "Your answer is wrong", "OK");
button.IsEnabled = false;
}
}
}
}
2. PropertyChangedEventArgs
You need to pass in the name of the property to PropertyChangedEventArgs.
They way PropertyChanged works is that it announces the name of the property that has changed. In this case, it needs to broadcast that the Score property has changed.
Let's use nameof(Score) to pass in the string "Score" to PropertyChangedEventArgs:
void OnScorePropertyChanged()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(displayScore)));
}
public int Score
{
get => score;
set
{
if (score != value)
{
score = value;
OnScorePropertyChanged();
}
}
}

Old ASP.NET code works on one computer, not on another?

So in my global.asax, I've got the following code:
Inventory.BusinessTier bt = new Inventory.BusinessTier();
string UserLogin = bt.ExtractLogin (Request.ServerVariables ["AUTH_USER"]);
Inventory.User myUser = new Inventory.User (UserLogin);
Session ["User"] = myUser;
It works just fine on one development PC, but using the same version of Visual Studio, it craps out on the third line with this error:
System.TypeInitializationException: 'The type initializer for
'Inventory.DataTier' threw an exception.'
Inner Exception
NullReferenceException: Object reference not set to an instance of an
object.
Other than a line adding impersonation in my web.config (it has to be there now), I haven't changed a single thing. Is there a way to get more info on this? I can't even trace it, because if I put a debug line in the User object constructor, it never hits it. I'm at a bit of a loss. Would appreciate any advice.
EDIT to answer questions below:
InventoryUser is a very simple user object that reads the current from the database and stores some basic user info in properties, such as UserID, Role, RoleID, and IsAdmin.
The DataTier class is a class that interacts with the database. It is used in multiple projects, so I'm quite sure it's not the problem. I tried to paste in the code anyway, but it exceeded the limit for a post.
I'm reasonably sure the problem is related to the user class. It's short, so I can paste it in here:
using System;
using System.Data;
// This is the user business object. It contains information pertaining to the current user of the application. Notably, it
// contains the department ID, which determines what inventory items the user will see when using the application. Only
// specified employees with admin access can see all items for all departments, and that is determined by a specific department ID.
namespace Inventory {
public class User {
private Guid _UserID;
private Guid _RoleID;
private Guid _UserDepartmentID;
private string _UserRole = "";
private string _UserName = "";
private bool _IsAuthorizedUser = false;
private bool _IsAdmin = false;
// Attribute declarations
public Guid UserID {
get {
return _UserID;
}
set {
_UserID = value;
}
}
public string UserRole {
get {
return _UserRole;
}
set {
_UserRole = value;
}
}
public Guid RoleID {
get {
return _RoleID;
}
set {
_RoleID = value;
}
}
public string UserName {
get {
return _UserName;
}
set {
_UserName = value;
}
}
public Guid UserDepartmentID {
get {
return _UserDepartmentID;
}
set {
_UserDepartmentID = value;
}
}
public bool IsAdmin {
get {
return _IsAdmin;
}
set {
_IsAdmin = value;
}
}
public bool IsAuthorizedUser {
get {
return _IsAuthorizedUser;
}
set {
_IsAuthorizedUser = value;
}
}
// -----------------
// - Constructor -
// -----------------
public User (string UserLogin) {
string ShortUserLogin = ExtractLogin (UserLogin);
GetUser (ShortUserLogin);
}
// ------------------
// - ExtractLogin -
// ------------------
public string ExtractLogin (string Login) {
// The domain and "\" symbol must be removed from the string, leaving only the user name.
int pos = Login.IndexOf (#"\");
return Login.Substring (pos + 1, Login.Length - pos - 1);
}
// -------------
// - GetUser -
// -------------
// This method is called to fill the user object based on the user's login. It ultimately gets authorized user data
// from the user table.
public void GetUser (string UserName) {
DataTier dt1 = new DataTier();
DataTable dt = dt1.GetUserInfo (UserName);
int RecordCount = dt.Rows.Count;
switch (RecordCount) {
case 1: // There is one user name match, as there should be. This is the likely situation.
DataRow dr = dt.Rows[0];
UserID = (Guid)dr ["UserID"];
UserRole = (string)dr ["UserRole"];
RoleID = (Guid)dr ["RoleID"];
this.UserName = UserName;
UserDepartmentID = (Guid)dr ["DepartmentID"];
IsAdmin = (bool)dr ["IsAdmin"];
IsAuthorizedUser = true;
break;
case 0: // There are no user name matches (unauthorized use).
IsAdmin = false;
IsAuthorizedUser = false;
break;
default: // There are multiple user name matches (problem!).
IsAdmin = false;
IsAuthorizedUser = false;
break;
}
}
}
}

Select ID from Picker

I am getting values in picker from an API, text and Value are two fields as I declared ! I am able to see values in it ! I want that whenever I select item from It, I am able to fetch respective value of that field !
async void CallInspectionMaster()
{
string Url = "192.168.xx.xx/api/QMSin/GetInspectionMasterList";
var data = await Url.GetJsonAsync<List<MyClass>>();
InspectionMasterPicker.ItemsSource = data;
InspectionMasterPicker.ItemDisplayBinding = new Binding("Text");
Binding selecteditemx = new Binding("InspectionMaster");
selecteditemx.Mode = BindingMode.TwoWay;
selecteditemx.Source = InspectionMasterPicker;
}
public class MyClass
{
public string Value { get; set; }
public string Text { get; set; }
}
I have to display text but fetch value so I can pass it other functions ! How do do that ?
assign a handler to the SelectedIndexChanged event
InspectionMasterPicker.SelectedIndexChanged += PickerSelect;
then create the handler
protected void PickerSelect(object sender, EventArgs args)
{
var item = (MyClass)InspectionMasterPicker.SelectedItem;
...
}
there is a complete example included in the docs

Cefsharp Custom Prompt

How can i make custom Prompt?
I tried with code below..
public static string ShowDialog(string text, string caption) {
Form prompt = new Form() {
Width = 500,
Height = 150,
FormBorderStyle = FormBorderStyle.FixedDialog,
Text = caption,
StartPosition = FormStartPosition.CenterScreen
};
Label textLabel = new Label() { Left = 50, Top = 20, Text = text };
TextBox textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
Button confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70, DialogResult = DialogResult.OK };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(textBox);
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.AcceptButton = confirmation;
return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
}
And then am using it like below
public bool OnJSDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, CefJsDialogType dialogType, string messageText, string defaultPromptText, IJsDialogCallback callback, ref bool suppressMessage) {
if(dialogType.ToString() == "Prompt") {
//Form prompt = ShowDialogClass.ShowDialog("as", "asd");
string promptValue = Components.ShowDialog("Test", "123");
if (promptValue != "") {
callback.Continue(true, promptValue);
} else {
callback.Continue(false, "");
};
};
But i am getting error.
System.InvalidOperationException: 'Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.'
return false;
}
How can i implement this dialog to show custom prompt?
Few months too late but, here you go.
You are trying to create a new Form(your prompt form) inside another thread. In this case your CEF browser thread that will create a object from class IJsDialogHandler will be on another thread than the prompt message thread so you have to Cross the thread to access it.
The way you do this is "Invoke"(saying something like "wo wo don't worry, i know what i'm doing"). When you use "Invoke" your asking for a witness, well that witness should have the same kind of capabilities as your prompt message box form so.... in this case form that creates the CEF browser. so the code should be something like this
public bool OnJSDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, CefJsDialogType dialogType, string messageText, string defaultPromptText, IJsDialogCallback callback, ref bool suppressMessage) {
if(dialogType.ToString() == "Prompt") {
if (ParentForm.InvokeRequired)
{
ParentForm.Invoke((MethodInvoker)delegate ()
{
string promptValue = Components.ShowDialog(messageText, "Prompt Message");
if (promptValue != "") {
callback.Continue(true, promptValue);
} else {
callback.Continue(false);
}
}
}
suppressMessage = false;
return true;
}
}
ParentForm should be changed to the name of the form that initialize the CEF browser.

ASP.NET custom controls - custom property doesn't hold the assigned value on postaback

I have a custom asp-net control that inherits from another one and its works as expected, though the properties are only set properly if i code them in the markup directly, so for instance if i need set a property at runtime that is some dynamic value, this value is never set or somehow lost.
Here's the markup code:
<!--related form-->
<fw:advancedformdisplay id="formDisp" runat="server" captchaenabled="true" EmailEnabled="true" EnableViewState="true" captchaprivatekey="xxxxxxxxxxxxxxxxxxxx" captchapublickey="xxxxxxxxxxxxx" captchatheme="white" SourceType="MenuItem" SourceMainId="Auto">
</fw:advancedformdisplay>
This is the code of the control:
[DefaultProperty("CaptchaEnabled"),ToolboxData("<{0}:AdvancedFormDisplay runat=server></{0}:AdvancedFormDisplay>"), Description("This is an enhanced FormDisplay control that inlcudes Googles Captcha control is enabled")]
public class AdvancedFormDisplay :SiteBuilder.WebControls.FormDisplay
{
bool _CaptchaEnabled = false, sendEmail = false;
string captchaErrorMessage = "The verification code entered is not valid. Please try again!";
RecaptchaControl captchaControl = null;
string captchaPrivateKey = "", captchaPublicKey = "", captchaTheme = "clean";
string originalFormHtml = string.Empty;
string afterText = string.Empty, beforeText = string.Empty;
Literal litHtmlForm = null;
string captchaErrorClass = "errorCaptcha";
public string EmailBeforeText
{
get { return beforeText; }
set { beforeText = value; }
}
public string EmailAfterText
{
get { return afterText; }
set { afterText = value; }
}
public string CaptchaErrorClass
{
get { return captchaErrorClass; }
set { captchaErrorClass = value; }
}
public bool CaptchaEnabled
{
get { return _CaptchaEnabled; }
set { _CaptchaEnabled = value; }
}
public bool EmailEnabled
{
get { return sendEmail; }
set { sendEmail = value; }
}
public string CaptchaErrorMessage
{
get { return captchaErrorMessage; }
set { captchaErrorMessage = value; }
}
/// <summary>
/// red,white,blackglass,clean
/// </summary>
public string CaptchaTheme
{
get { return captchaTheme; }
set { captchaTheme = value; }
}
public string CaptchaPrivateKey
{
get { return captchaPrivateKey; }
set { captchaPrivateKey = value; }
}
public string CaptchaPublicKey
{
get { return captchaPublicKey; }
set { captchaPublicKey = value; }
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
public override void OnSaved(FormDisplayEventArgs e)
{
//If captcha control is enabled we need to adda bit of code to redirect form properly
if (CaptchaEnabled && e.Redirect && !e.SendMail)
{
//Do Stuff
}
if(sendEmail)
{
//Send email
}
base.OnSaved(e);
}
public override void OnSaving(FormDisplayEventArgs e)
{
if (CaptchaEnabled)
{
//Validate and do stuff
}
base.OnSaving(e);
}
}
And then in my asp.net page that is using control, created by markup code, in the Page_Load() i try to assign some values to some properties and and the values aren't set properly, meaning that if i have set for isntance, the property EmailBeforeText = "somthing" this value will not be assigned..
protected void Page_Load(object sender, EventArgs e)
{
//2: Get the language of menuitem - Based on current culture setting (for by dropdownbox - change logic)
try
{
currentCulture = Thread.CurrentThread.CurrentCulture.ToString();
// Redirect if domain does not match rootnode.
DomainChecker.CheckURL(this.Request, this.Response, currentCulture);
if (footerArticle != null)
footerArticle.SourceMenuId = Digimaker.Config.Custom.Get("FooterID_" + currentCulture).ToString();
}
catch
{
currentCulture = "en-GB";
if( footerArticle != null )
footerArticle.SourceMenuId = Digimaker.Config.Custom.Get("FooterID_" + currentCulture).ToString();
}
Any ideas what i'm missing here?
Thanks a lot for your reading!
Regards,
byte_slave
short answer: use viewstate to persist your custom values!
Understanding ASP.NET ViewState whitepaper (see example with NavigateUrl)
edit: as reading the white-paper is obviously a really hard thing:
Each control is responsible for storing its own state, which is
accomplished by adding its changed state to its ViewState property.
The ViewState property is defined in the System.Web.UI.Control class,
meaning that all ASP.NET server controls have this property available.
(When talking about view state in general I'll use lower case letters
with a space between view and state; when discussing the ViewState
property, I'll use the correct casing and code-formatted text.)
If you examine the simple properties of any ASP.NET server control
you'll see that the properties read and write directly to the view
state. (You can view the decompiled source code for a .NET assembly by
using a tool like Reflector.) For example, consider the HyperLink Web
control's NavigateUrl property. The code for this property looks like
so:
public string NavigateUrl
{
get
{
string text = (string) ViewState["NavigateUrl"];
if (text != null)
return text;
else
return string.Empty;
}
set
{
ViewState["NavigateUrl"] = value;
}
}
As this code sample illustrates, whenever a control's property is
read, the control's ViewState is consulted. If there is not an entry
in the ViewState, then the default value for the property is returned.
When the property is assigned, the assigned value is written directly
to the ViewState.

Resources