Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mvvmcross binding in release mode

I've been using MvvMCross for a while now and this code has been working. I did install the latest updates, but I can't swear that this is when the problem started. What is happening is that I have a login screen with simple text bindings to the user name and password. When I compile with Use Shared Runtime, it works fine. When this is not checked, it doesn't bind the text to the text fields. My Layout is as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
<LinearLayout
    android:layout_width="250dp"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="50dp"
    android:background="@drawable/borderdoublewidth">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            style="@style/InputTextView"
            android:text="User Name" />
        <EditText
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/txtUserName"
            style="@style/InputEditText"
            local:MvxBind="Text UserName" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            style="@style/InputTextView"
            android:text="Password" />
        <EditText
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/txtPassword"
            android:inputType="textPassword"
            android:password="true"
            style="@style/InputEditText"
            local:MvxBind="Text Password" />
    </LinearLayout>
    <Button
        android:text="Login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        local:MvxBind="Click CheckLogin" />
</LinearLayout>
</LinearLayout>

My View Model is as follows:

class LoginViewModel : MvxViewModel
{

    public void Init()
    {
    }

    public override void Start()
    {
        base.Start();

        Task.Run(async () =>
        {
            var l = await ListDataSource.GetLocations();
            Locations = l.Location.ToArray<string>();
        });
    }

    public string Location
    {
        get
        {
            return Settings.Location;
        }
        set
        {
            Settings.Location = value;
            RaisePropertyChanged(() => Location);
        }
    }

    private string[] _Locations;
    public string[] Locations
    {
        get
        {
            return _Locations;
        }
        set
        {
            _Locations = value;
            RaisePropertyChanged(() => Locations);
        }
    }

    private string _UserName;
    public string UserName
    {
        get
        {
            return _UserName;
        }
        set
        {
            _UserName = value;
            RaisePropertyChanged(() => UserName);
            EventLog.Debug("UserName Changed <" + _UserName + ".");
        }
    }

    private string _Password;
    public string Password
    {
        get
        {
            return _Password;
        }
        set
        {
            _Password = value;
            RaisePropertyChanged(() => Password);
        }
    }

    public IMvxCommand CheckLogin
    {
        get
        {
            return new MvxCommand(() =>
                ValidateDriver()
                );
        }
    }

    private bool LoggingIn = false;
    private async void ValidateDriver()
    {
        if (Settings.Location == null)
        {
            MiscFunctions.messageBox("Please set the Location!");
            return;
        }
        if (LoggingIn)
            return;

        LoggingIn = true;

        //btnLogin.Focus(Windows.UI.Xaml.FocusState.Programmatic);
        string VersionName = "";
        MPS_Mobile_Warehouse.Droid.Views.LoginView act = (Mvx.Resolve<IMvxAndroidCurrentTopActivity>().Activity as MPS_Mobile_Warehouse.Droid.Views.LoginView) ?? null;
        if (act != null)
        {
            VersionName = act.GetAppVersionName();
        }

        //DriverName gets set in this call.
        if (await ShipmentDataSource.CheckTabletUser(UserName, Password, VersionName))
        {
            ShowViewModel<MainViewModel>();
        }
        LoggingIn = false;
    }


}

The binding to the CheckLogin Button binding seems to work fine. When it makes the call to CheckTabletUser, the UserName and Password properties are blank.

I am editing this so people can see my LinkerPleaseInclude.cs file. It is the vanilla one that comes with the MvvmCross Starter Pack:

public class LinkerPleaseInclude
{
    public void Include(Button button)
    {
        button.Click += (s, e) => button.Text = button.Text + "";
    }

    public void Include(CheckBox checkBox)
    {
        checkBox.CheckedChange += (sender, args) => checkBox.Checked = !checkBox.Checked;
    }

    public void Include(Switch @switch)
    {
        @switch.CheckedChange += (sender, args) => @switch.Checked = [email protected];
    }

    public void Include(View view)
    {
        view.Click += (s, e) => view.ContentDescription = view.ContentDescription + "";
    }

    public void Include(TextView text)
    {
        text.TextChanged += (sender, args) => text.Text = "" + text.Text;
        text.Hint = "" + text.Hint;
    }

    public void Include(CheckedTextView text)
    {
        text.TextChanged += (sender, args) => text.Text = "" + text.Text;
        text.Hint = "" + text.Hint;
    }

    public void Include(CompoundButton cb)
    {
        cb.CheckedChange += (sender, args) => cb.Checked = !cb.Checked;
    }

    public void Include(SeekBar sb)
    {
        sb.ProgressChanged += (sender, args) => sb.Progress = sb.Progress + 1;
    }

    public void Include(Activity act)
    {
        act.Title = act.Title + "";
    }

    public void Include(INotifyCollectionChanged changed)
    {
        changed.CollectionChanged += (s, e) => { var test = $"{e.Action}{e.NewItems}{e.NewStartingIndex}{e.OldItems}{e.OldStartingIndex}"; };
    }

    public void Include(ICommand command)
    {
        command.CanExecuteChanged += (s, e) => { if (command.CanExecute(null)) command.Execute(null); };
    }

    public void Include(MvvmCross.Platform.IoC.MvxPropertyInjector injector)
    {
        injector = new MvvmCross.Platform.IoC.MvxPropertyInjector();
    }

    public void Include(System.ComponentModel.INotifyPropertyChanged changed)
    {
        changed.PropertyChanged += (sender, e) => {
            var test = e.PropertyName;
        };
    }

    public void Include(MvxTaskBasedBindingContext context)
    {
        context.Dispose();
        var context2 = new MvxTaskBasedBindingContext();
        context2.Dispose();
    }
}

I fixed my issue by reverting to MvvmCross version 4.3.0. I am leaving this open in case a developer needs to know what is going on in the latest version.

like image 862
Jim Wilcox Avatar asked Nov 29 '16 19:11

Jim Wilcox


1 Answers

MvvmCross uses the AfterTextChanged event instead of TextChanged to listen for changes in EditText/TextView. In your LinkerPleaseInclude.cs you should just need to change to use the AfterTextChanged event. Then you should have no issues with v4.4.

public void Include(TextView text)
{
   text.AfterTextChanged += (sender, args) => text.Text = "" + text.Text;
   text.Hint = "" + text.Hint;
}
like image 126
Plac3Hold3r Avatar answered Dec 15 '22 01:12

Plac3Hold3r