gpt4 book ai didi

mvvmcross - MvvmCross,Mvx.MvxListView和MvxItemTemplate中的自定义绑定(bind)

转载 作者:行者123 更新时间:2023-12-03 07:57:59 29 4
gpt4 key购买 nike

在MvvmCross应用程序中,我有一个页面具有经典的聊天行为(类似于WhatsApp):此页面显示了两个用户之间交换的消息的历史记录,最后一条消息位于列表的底部。
我已经在Windows Phone 8.1中成功实现了视图,但是在Android中遇到了问题。

我将为您简要介绍和描述我的问题,然后我将详细介绍技术细节。

介绍

实际上,我需要对不同用户发送的消息应用不同的样式:始终对齐其他用户发送的左消息,并对齐我发送的右消息(我通过weight属性执行此操作);我需要应用不同的drawable背景并设置不同的gravity属性。
我使用自定义绑定,因为AFAIK不能使用经典绑定来绑定那些属性:local:MvxBind="Gravity MyPropery"不起作用,因为没有Gravity属性。

因此,我当然有两个axml文件:


第一个包含Mvx.MvxListView
第二个包含MvxListView的项目模板


根据这些指南,我创建了三种不同的自定义绑定(用于背景,重力和权重):


http://slodge.blogspot.it/2013/06/n28-custom-bindings-n1-days-of-mvvmcross.html
In MvvmCross how do I do custom bind properties


问题

我希望当用户打开聊天视图时,列表小部件会自动显示最后一条消息。为此,我以编程方式将列表滚动到最后一条消息,这似乎是问题所在。

如果不以编程方式滚动,则在打开页面并手动滚动到页面末尾时,所有自定义绑定都将成功应用:我可以看到消息左右对齐,并应用了正确的背景和粗细。

如果我以编程方式强制滚动,则在打开页面时会看到一个奇怪的行为:所有消息都存在(经典绑定(例如Text属性)已成功应用),但是缺少自定义绑定。所有消息都具有相同的背景,并且都左对齐。
但是,如果我手动上下滚动,则将处理自定义绑定,并以正确的样式显示消息。

调试分析

为了调试行为,我在自定义绑定过程中放置​​了一个简单的静态计数器,以跟踪每次处理函数时的情况。

public class LinearLayoutWeightTargetBinding : MvxAndroidTargetBinding
{
public static int debugCounter = 0;
public LinearLayoutWeightTargetBinding(object target) : base(target)
{
}

protected LinearLayout MyTarget
{
get { return (LinearLayout)Target; }
}

public override Type TargetType { get { return typeof(bool); } }

protected override void SetValueImpl(object target, object value)
{
var ll = (LinearLayout)target;
var itsMe = (bool)value;
var weight = itsMe ? (float)20.0 : (float)5.0;

var layoutParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WrapContent, weight);
ll.LayoutParameters = layoutParams;
Log.Debug("MeeCHAT", string.Format("LinearLayoutWeightTargetBinding::SetValueImpl::ItsMe:{0} - counter:{1}", itsMe, ++debugCounter));
}

public override MvxBindingMode DefaultMode { get {return MvxBindingMode.TwoWay;} }
}


通过这种方式,我看到实际上是通过上下滚动自定义绑定来应用的(debugCounter正确增加了)。
但是,当我以编程方式应用滚动时,自定义绑定仅处理前10个项目,这似乎就是为什么我看到的消息没有正确样式的原因。因为我的清单很长,所以仅处理了前10个项目,但它们是不可见的(它们在可见区域之外),并且未处理可见项目。

技术细节

以下是与我的应用程序的技术方面相关的一些详细信息。我尝试给您所有重要方面。

意见组织
通过遵循Greg Shackles在本文 http://gregshackles.com/presenters-in-mvvmcross-navigating-android-with-fragments/中描述的方法,我对应用程序只有一个通用 Activity,对于每个 Fragment只有一个 View。然后可以通过 Presenter激活正确的ViewModel并管理导航堆栈。

我有 Mvx.MvxListView小部件的视图的片段是

public class MyMatchersChatView : MvxFragment
{
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignore = base.OnCreateView(inflater, container, savedInstanceState);
var result = this.BindingInflate(Resource.Layout.MyMatchersChatView, null);

var headerFrame = result.FindViewById<FrameLayout>(Resource.Id.headerFrameMyMatchersChatView);
var headerWidget = new HeaderWidget() { ViewModel = this.ViewModel };
var tran = ChildFragmentManager.BeginTransaction();
tran.Add(headerFrame.Id, headerWidget, "headerMyMatchersChat");
tran.Commit();

var listView = result.FindViewById<MvxListView>(Resource.Id.messagesList);
listView.SetSelection(listView.Adapter.Count - 1); // Scroll to the end of the list
return result;
}
}


语句 listView.SetSelection(listView.Adapter.Count - 1);强制列表滚动到末尾。

最后两件事:如何注册自定义绑定以及如何在axml文件中应用。

定制绑定注册

在Setup.cs中,我有:

protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxCustomBindingFactory<LinearLayout>("CustomWeight",
(b) => new LinearLayoutWeightTargetBinding(b)));
}


自定义绑定的应用

在我的axml中,我有:

<LinearLayout 
android:orientation="horizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
local:MvxBind="CustomWeight IsCurrentUser">




列表视图和视图模型

这是ListView的代码

<Mvx.MvxListView
android:id="@+id/messagesList"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
local:MvxBind="ItemsSource MyMessages"
local:MvxItemTemplate="@layout/mymatcherschatview_itemtemplate" />


和ViewModel中的属性

    private IEnumerable<MyMatchMessageModel> _myMessages;
public IEnumerable<MyMatchMessageModel> MyMessages
{
get { return _myMessages; }
set
{
_myMessages = value;
RaisePropertyChanged(() => MyMessages);
}
}


环境
最后,这是我的环境:


Visual Studio 2015
MvvmCross 3.5.1
核心目标:.NET Framework 4.5,Windows 8,ASP.NET Core 5.0,Windows Phone 8.1,Xamarin.Android,Xamarin.iOS,Xamarin.iOS(经典)
Android应用程序的目标是API级别19(Xamarin.Android v4.4支持)
Xamarin 3.11.1450.0
Xamarin.Android 5.1.6.7


有人可以帮助我了解我做错了什么吗?
感谢您的阅读和任何帮助!

>>编辑1 <<

我已经通过添加 stackFromBottomtranscriptMode属性并通过在 Fragment中以编程方式删除滚动到下面的滚动以获得自动滚动行为来更改布局,但是问题仍然存在:要查看具有正确样式的消息,我必须手动上下滚动(激活自定义绑定)

这是新的axml ...

<Mvx.MvxListView
android:id="@+id/messagesList"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll"
local:MvxBind="ItemsSource MyMessages"
local:MvxItemTemplate="@layout/mymatcherschatview_itemtemplate" />


...以及Fragment中的新代码

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignore = base.OnCreateView(inflater, container, savedInstanceState);
var result = this.BindingInflate(Resource.Layout.MyMatchersChatView, null);

var headerFrame = result.FindViewById<FrameLayout>(Resource.Id.headerFrameMyMatchersChatView);
var headerWidget = new HeaderWidget() { ViewModel = this.ViewModel };
var tran = ChildFragmentManager.BeginTransaction();
tran.Add(headerFrame.Id, headerWidget, "headerMyMatchersChat");
tran.Commit();

return result;
}

最佳答案

我要做的第一件事是确保自定义绑定始终被调用。
SetValueImpl()方法上设置一个断点,并检查是否在那些有问题的项目上调用了该断点。如果发生这种情况,则问题取决于视图不会由于任何原因而被更新,因此您应该对此进行处理。如果它没有损坏,您将确定它是MvxAdapter中的一个自定义绑定问题(可能是错误)。

如果您发现它是第二个。我建议您摆脱自定义绑定,并按如下方式创建自己的ChatListAdapter : MvxAdapter

public class CoolChatListAdapter : MvxAdapter
{
public CoolChatListAdapter(Context context, IMvxAndroidBindingContext bindingContext) : base(context, bindingContext)
{
}

protected override View GetBindableView(View convertView, object source, int templateId)
{
var item = source as MyMatchMessageModel;
var weight = item.IsCurrentUser ? (float) 20.0 : (float) 5.0;

var ll = (LinearLayout) convertView;
var layoutParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WrapContent, weight);
ll.LayoutParameters = layoutParams;

return base.GetBindableView(convertView, source, templateId);
}
}


然后,在您的android视图中:

var adapter = new ChatListAdapter(this, (IMvxAndroidBindingContext)BindingContext);
_chatList = FindViewById<MvxListView>(Resource.Id.chat_list_view);
_chatList.Adapter = adapter;

关于mvvmcross - MvvmCross,Mvx.MvxListView和MvxItemTemplate中的自定义绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34691544/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com