我的 Android 应用程序有点问题,我不知道如何使用 MVVM Cross 解决它。
这是我的模型
public class Article
{
string Label{ get; set; }
string Remark { get; set; }
}
我的 View 模型
public class ArticleViewModel: MvxViewModel
{
public List<Article> Articles;
....
}
我的layout.axml ...
<LinearLayout
android:layout_width="0dip"
android:layout_weight="6"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/layoutArticleList">
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/editSearch"
android:text=""
android:singleLine="True"
android:selectAllOnFocus="true"
android:capitalize="characters"
android:drawableLeft="@drawable/ic_search_24"
local:MvxBind="{'Text':{'Path':'Filter','Mode':'TwoWay'}}"
/>
<Mvx.MvxBindableListView
android:id="@+id/listviewArticle"
android:choiceMode="singleChoice"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
local:MvxItemTemplate="@layout/article_rowlayout"
local:MvxBind="{'ItemsSource':{'Path':'Articles'}}" />
</LinearLayout>
...
我的问题来了,“article_rowlayout”
...
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/blue">
<TextView
android:id="@+id/rowArticleLabel"
android:layout_width="0dip"
android:layout_weight="14"
android:layout_height="wrap_content"
android:textSize="28dip"
local:MvxBind="{'Text':{'Path':'Label'}}" />
<ImageButton
android:src="@drawable/ic_modify"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/rowArticleButtonModify"
android:background="@null"
android:focusable="false"
android:clickable="true"
local:MvxBind="{'Click':{'Path':'MyTest'}}"
/>
...
名为“MyTest”的“单击”命令链接到 MvxBindableListView 提供的项目上。换句话说,单击在我的模型“文章”中搜索命令“MyTest”,而不是我的 ViewModel。如何更改该行为以链接负责我的 MvxBindableListView 的 ViewModel“ArticleViewModel”?
有什么建议吗?
最佳答案
关于点击事件尝试绑定(bind)的位置,您的分析绝对正确。
我通常采用两种方法:
- 在列表中使用 ItemClick
- 继续使用 Click,但在 ViewModel 端做一些重定向。
所以...1
Main Menu在教程中有一个 ViewModel 有点像:
public class MainMenuViewModel
: MvxViewModel
{
public List<T> Items { get; set; }
public IMvxCommand ShowItemCommand
{
get
{
return new MvxRelayCommand<T>((item) => /* do action with item */ );
}
}
}
这在 axml 中用作:
<Mvx.MvxBindableListView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res/Tutorial.UI.Droid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
local:MvxBind="{'ItemsSource':{'Path':'Items'},'ItemClick':{'Path':'ShowItemCommand'}}"
local:MvxItemTemplate="@layout/listitem_viewmodel"
/>
此方法只能用于整个列表项上的 ItemClick - 不能用于列表项中的单个 subview 。
或者...2
因为我们没有任何 RelativeSource
mvx 中的绑定(bind)指令,这种类型的重定向可以在 ViewModel/Model 代码中完成。
这可以通过呈现模型对象的启用行为的包装器而不是模型对象本身来完成 - 例如使用 List<ActiveArticle>
:
public ActiveArticle
{
Article _article;
ArticleViewModel _parent;
public WrappedArticle(Article article, ArticleViewModel parent)
{
/* assignment */
}
public IMvxCommand TheCommand { get { return MvxRelayCommand(() -> _parent.DoStuff(_article)); } }
public Article TheArticle { get { return _article; } }
}
然后您的 axml 将不得不使用如下绑定(bind):
<TextView ...
local:MvxBind="{'Text':{'Path':'TheArticle.Label'}}" />
和
<ImageButton
...
local:MvxBind="{'Click':{'Path':'TheCommand.MyTest'}}" />
此方法的一个示例是使用 WithCommand 的 session 示例
但是...请注意,使用WithCommand<T>
时我们发现了内存泄漏 - 基本上 GarbageCollection 拒绝收集嵌入的 MvxRelayCommand
- 这就是为什么 WithCommand<T>
是IDisposable
为什么BaseSessionListViewModel清除列表并在分离 View 时处理 WithCommand 元素。
评论后更新:
如果您的数据列表很大 - 并且您的数据是固定的(您的文章是没有 PropertyChanged 的模型)并且您不想承担创建大型 List<WrappedArticle>
的开销那么解决这个问题的一种方法可能是使用 WrappingList<T>
类。
这与 Microsoft 代码中采用的方法非常相似 - 例如在 WP7/Silverlight 中虚拟化列表 - http://shawnoster.com/blog/post/Improving-ListBox-Performance-in-Silverlight-for-Windows-Phone-7-Data-Virtualization.aspx
对于您的文章,这可能是:
public class ArticleViewModel: MvxViewModel
{
public WrappingList<Article> Articles;
// normal members...
}
public class Article
{
public string Label { get; set; }
public string Remark { get; set; }
}
public class WrappingList<T> : IList<WrappingList<T>.Wrapped>
{
public class Wrapped
{
public IMvxCommand Command1 { get; set; }
public IMvxCommand Command2 { get; set; }
public IMvxCommand Command3 { get; set; }
public IMvxCommand Command4 { get; set; }
public T TheItem { get; set; }
}
private readonly List<T> _realList;
private readonly Action<T>[] _realAction1;
private readonly Action<T>[] _realAction2;
private readonly Action<T>[] _realAction3;
private readonly Action<T>[] _realAction4;
public WrappingList(List<T> realList, Action<T> realAction)
{
_realList = realList;
_realAction = realAction;
}
private Wrapped Wrap(T item)
{
return new Wrapped()
{
Command1 = new MvxRelayCommand(() => _realAction1(item)),
Command2 = new MvxRelayCommand(() => _realAction2(item)),
Command3 = new MvxRelayCommand(() => _realAction3(item)),
Command4 = new MvxRelayCommand(() => _realAction4(item)),
TheItem = item
};
}
#region Implementation of Key required methods
public int Count { get { return _realList.Count; } }
public Wrapped this[int index]
{
get { return Wrap(_realList[index]); }
set { throw new NotImplementedException(); }
}
#endregion
#region NonImplementation of other methods
public IEnumerator<Wrapped> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(Wrapped item)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(Wrapped item)
{
throw new NotImplementedException();
}
public void CopyTo(Wrapped[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public bool Remove(Wrapped item)
{
throw new NotImplementedException();
}
public bool IsReadOnly { get; private set; }
#endregion
#region Implementation of IList<DateFilter>
public int IndexOf(Wrapped item)
{
throw new NotImplementedException();
}
public void Insert(int index, Wrapped item)
{
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
throw new NotImplementedException();
}
#endregion
}
关于android - MVVM 在 MvxBindableListView 中交叉更改 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12682082/