mvvmcross binding in release mode
Asked Answered
B

1

5

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.

Buskin answered 29/11, 2016 at 19:22 Comment(5)
Do you have the LinkerPleaseInclude.cs file in your project? This sounds vaguely familiar to #16924678Fistula
It's a common issue. All the properties like TextView.Text etc which you bind to should be mentioned in LinkerPleaseInclude.cs file which is autogenerated when you reference MvvmCross packages.Gutenberg
Yes. It is the version that comes in the MvvMCross starter pack. I even added an entry for EditText. EditText should be linked from having the default TextView, but I was trying anything I could think of.Buskin
@JimWilcox, just to confirm, in your LinkerPleaseInclude.cs you have an include for TextView and are subscribing to the AfterTextChanged? As EditText inherits TextView, having an include for TextView will cover both controls. Something along the lines <<the_textView_control>>.AfterTextChanged += (sender, args) => text.Text = "" + text.Text;Ansel
@Ansel I have already reverted to MvvmCross version 4.3.0 and it fixed the issue. If it will help, I will edit my OP to show my LinkerPleaseInclude.cs file.Buskin
A
7

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;
}
Ansel answered 30/11, 2016 at 5:25 Comment(1)
Thanks, this worked. I had installed the latest MvvmCross Starter Pack that includes the sample LinkerPleaseInclude.cs. I just verified that it still references text.TextChanged. I'm not sure who would be the one to update it, but it should probably be done. I will post this on GitHub.Buskin

© 2022 - 2024 — McMap. All rights reserved.