Android DataBinding - Как связать свойства ViewGroup - PullRequest
0 голосов
/ 29 апреля 2019

Я занимаюсь разработкой приложения для Android на Xamarin.Android (C #). Тем не менее, я чувствую, что на этот вопрос также могут ответить любые разработчики Java.

Я новичок в разработке для Android. В любом случае, я создал фрагмент с LinearLayout и TextView внутри. Когда я создаю для него фоновый класс, я не наследую (по словам JAVA, extend) его от класса Fragment, а от класса LinearLayout.

Итак, файл MyFragment.cs начинается так:

public class MyFragment : LinearLayout

Эквивалент JAVA будет

public class MyFragment extends LinearLayout

(P.S. Я ограниченно знаю JAVA и его синтаксис).

В любом случае, все работает нормально. У меня есть метод Initialize (в JAVA это должен быть метод Init), который раздувает вид фрагмента. С точки зрения, он пытается найти TextView с заданным Id.

Итак, коды выглядят так:

public class MyFragment : LinearLayout
{
 Context mContext;
  private void Initialize(Context ctx)
  {
        //Inflating the layout
        mContext = ctx;
        var inflatorService = (LayoutInflater)ctx.GetSystemService(Context.LayoutInflaterService);
        View v = inflatorService.Inflate(Resource.Layout.MyFragmentView, this, false);
        this.AddView(v);
        GoalHeader = v.FindViewById<TextView>(Resource.Id.GoalHeader);
  }

Пока все работает очень хорошо. Затем я продолжаю реализацию шаблона MVVM, используя библиотеку MVVMLight. Я создаю ViewModel следующим образом:

 public class Vm_MyFragment : ViewModelBase
{
    private string _goaltitle = "";
    public string GoalTitle
    {
        get { return _goaltitle; }
        set { Set(ref _goaltitle, value); }
    }
    public void SetTest()
    {
        DispatcherHelper.CheckBeginInvokeOnUI(() =>
        {
            GoalTitle = "Test";
        });
    }
}

Тем не менее, все хорошо. Проблема начинается, когда я пытаюсь привязать свойство текста TextView к свойству ViewModel GoalTitle следующим образом:

 private readonly List<Binding> _bindings = new List<Binding>();

 private void Initialize(Context ctx)
    {
        //Inflating the layout
        mContext = ctx;
        var inflatorService = (LayoutInflater)ctx.GetSystemService(Context.LayoutInflaterService);
        View v = inflatorService.Inflate(Resource.Layout.MyFragmentView, this, false);
        this.AddView(v);
        Vm_MyFragmentView viewmodel = new Vm_MyFragmentView();
        GoalHeader = v.FindViewById<TextView>(Resource.Id.GoalHeader);
        _bindings.Add(
            this.SetBinding(
                () => mainViewModel.GoalTitle,
                () => GoalHeader.Text));
    }

Примечание: Binding из пространства имен GalaSoft.MvvmLight.Helpers.

Я добавляю фрагмент в основной вид (я имею в виду вид MainActivity) и отлаживаю приложение. После выполнения я получаю следующую ошибку:

Не удалось активировать JNI-дескриптор 0xfff02a68 (key_handle 0x339790a) типа Java «md55bfae9a06327fa0fdf207b4f768604b1 / MyFragment» в качестве управляемого типа «TestApp.MyFragment».

Выполняя поиск в Google, я понял, что пытаюсь привязать свойство еще до того, как представление будет создано (исправьте меня, если я ошибаюсь). Предложения, которые я нашел в других ответах SO, заключались в том, чтобы либо поместить код в метод OnCreateView, либо как-то задержать выполнение кода связывающей части .

Первое решение не сработало для меня, так как LinearLayout aka View не имеет такого метода OnCreateView, который я могу переопределить.

Итак, как я могу связать TextView с ViewModel тогда? И также, я на правильном пути, рассматривая фрагмент как LinearLayout, поскольку я наследую от него?

1 Ответ

1 голос
/ 29 апреля 2019

Я не знаком с расширением MVVMLIght, но если вы используете фрагмент так, как он должен (т.е. в табуляции), вы должны наследовать от такого фрагмента (это фрагмент поддержки v4):

public class CategoryFragment : SupportFragment {
RecyclerView _recyclerView;
private View _view;

public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    _view = inflater.Inflate (Resource.Layout._CategoryLayout, container, false);

    // Get our RecyclerView layout:
    _recyclerView = _view.FindViewById<RecyclerView> (Resource.Id.categoryRecyclerView);

    // Instantiate the layout manager
    var linearLayoutManager = new LinearLayoutManager (Context, LinearLayoutManager.Vertical, false);
    _recyclerView.SetLayoutManager (linearLayoutManager);

    // Instantiate the adapter and pass in its data source:
    _adapter = new CategoryAdapter (_categories);
    //Register the item click handler with the adapter:
    _adapter.ItemClick += OnItemClick;
    // Plug the adapter into the RecyclerView:
    _recyclerView.SetAdapter (_adapter);
    return _view;
}

}

...