如何列表项结合到它是否包含在另一个集合 [英] How to binding list item to whether it is contained in another collection

查看:145
本文介绍了如何列表项结合到它是否包含在另一个集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该方案是我们在一个列表(ListView中Android和UITableView的在iOS上)显示的项目清单。所述的ItemSource来自web服务。除了该项目的数据属性,每一个项目都有它可以被加入到当前选择的项目的集合,这反映在上视图模型另一个集合的附加状态。

The scenario is that we have a list of items displayed in a list (ListView on Android and UITableView on iOS). The ItemSource comes from a web service. In addition to the data properties of the item, each of the items has the additional state that it can be added to a collection of currently selected items which is reflected in another collection on the view model.

我需要能够改变在列表中的项目的基础上是否是在当前选择的列表的显示。

I need to be able to alter the display of the item in the list based on whether it is in the currently selected list.

结合给出的的datacontext是来自的ItemsSource,这是仅仅指刚原始数据为一个项目,并且没有办法知道是否数据是当前所选的项目之一的数据。这已被要求视图模型来完成。

The datacontext given for binding is the data that comes from the ItemsSource, which is jsut the raw data for an item and has no way of knowing if that data is one of the currently selected items. That has to be done by asking the ViewModel.

我在努力寻找解决这一问题的最佳解决方案。我当然不希望修改的ItemsSource到伪属性源添加到每个项目。

I'm struggling to find the best solution to this problem. I certainly do not want to modify the ItemsSource to add a bogus property to each item in the source.

我可以通过重写适配器/ TableViewSource硬code这实际上并没有使用此绑定破解它周围的东西,但似乎错了。

I can hack something around it by overriding the Adapter/TableViewSource to hardcode this without actually using binding for this, but that seems wrong.

更新

这是没有解释得非常好,所以让我尝试使用现有MvvmCross例子为基础来解释。

That was not explained very well, so let me try to explain using an existing MvvmCross example as the basis.

考虑从N书籍样本= 6,N = 7。我们要增加一个新的功能,我们可以将其标记,我们已经拥有的书籍和那些我们已经标记它显示了一个指标来告诉你,你自己的书。

Consider the books sample from N=6 and N=7. We want to add a new feature where we can mark the books that we already own and for those that we have marked it shows an indicator to tell you that you own the book.

试想一下,视图模型具有类似的方法:

Imagine that the view model has methods like:

public bool IsOwned(string id)
public void SetOwned(string id, bool owned)

这些的实现是不是这个讨论很重要,但我想大概也需要某种形式的事件处理程序的通知时,所有权变更为一本书。

The implementation of those is not important for this discussion, but I would probably also need some form of Event Handler to notify when ownership has changed for a book.

我试图找出我怎么能建立在一个ListViewItem / TableViewCell的绑定,以便它可以利用在DataContext的ID为项目控制在一个UI元素的知名度查询的视图模型的IsOwned方法纪录。

I am trying to figure out how I can set up a binding on the ListViewItem/TableViewCell so that it can query the IsOwned method on the ViewModel using the ID from the DataContext for the item to control visibility of a UI element in that record.

我猜,我将不得不创建一个自定义源绑定,但绑定必须引用视图模型和DataContext的让我有点丢在这里。

I'm guessing that I will have to create a custom source binding, but that binding has to reference the ViewModel and the DataContext so I am a little lost here.

请注意,在我的真正的问题,我试图解决,是否一些标记的状态是暂时的,本地只对视图模型(如果我离开它不是想起了屏幕)。这precludes有获取信息的服务理念。

Note that in my real problem I am trying to solve, the status of whether something is marked is temporary and local only to the ViewModel (if I exit the screen it is not remembered). This precludes the idea of having a Service for getting the information.

推荐答案

您的UI列表项单元都有一个DataContext其控件绑定到 - 这是DataContext的细胞自身个人视图模型

Your UI list item cell has a DataContext that its controls bind to - that DataContext is the cell's own individual ViewModel.

MvvmCross没有(如V3.1今天)让你看看这外面的DataContext - 它不会让你(例如)检查另一的UIElement的DataContext的或不会让你问一个父

MvvmCross doesn't (as of v3.1 today) let you look outside that DataContext - it doesn't let you (for example) inspect another UIElement's DataContext or doesn't let you ask for a Parent.

要在这方面的工作,我通常创造我的DataContext我的列表项细胞的,使它们包含的所有数据和动作,这些细胞需要 - 这样他们是真正的视图模型的列表项视图。哪里有一些方便的Model类重用,那么这往往意味着我创建了一个包装类,以协助DataContext的。偶尔(很少),我将在ValueConverter做到这一点(见下面),但总的来说,我将使用由视图模型暴露的包装类,而是执行此操作。

To work within this, I generally create my DataContext for my list item cell's so that they contain all the data and actions that those cells need - so that they are genuinely the ViewModel for the list item view. Where there is some convenient Model class to reuse, then this will often mean that I create a wrapper class to assist with the DataContext. Occasionally (rarely) I will do this in a ValueConverter (see below)*, but in general I will do this using wrapper classes exposed by the ViewModel instead.

例如,对于像你的情况,如果我有一个列表<富> 作为我的核心模型,然后在页面级视图模型我将创建一个 FooWithSelectionState 类:

For example, for something like your case, if I had a List<Foo> as my core model, then in the page level ViewModel I would create a FooWithSelectionState class:

public class FooWithSelectionState : MvxNotifyPropertyChanged
{
    public Foo Foo { get; set; /* normal INPC in here */ }
    public bool IsSelected { get; set; /* normal INPC in here */ }
}

这将然后让我的ViewModel揭露一个列表&LT; FooWithSelectedState&GT; 作为一个属性 - 个体列表项的细胞就可以绑定到 IsSelected ,以及像基础对象的链接属性 Foo.Name

This would then allow my ViewModel to expose a List<FooWithSelectedState> as a Property - and individual list item cells can then bind to IsSelected as well as to chained properties of the underlying object like Foo.Name.

架构上来说,这种模式是强大的,它是可测试的,它的清洁,并在每一个列表项单元都有自己的明确定义的视图模型是正确的。不过,我明白它觉得有点code-重 - 它可以感觉有点大材小用。在某些情况下,开发的只想直接使用Model类没有一个ViewModel一步。也许在未来的某个MVX的版本,则Mvv​​mCross可能会添加一些替代机制,让数据绑定UI元素外看自己的DataContext的 - 这在例如有人建议 https://github.com/MvvmCross/MvvmCross/issues/35 - 但今天这个不存在(据我所知)

Architecturally, this pattern is robust, it's testable, it's clean and it's "correct" in that each list item cell has its own well-defined ViewModel. However, I do understand it can feel a bit code-heavy - it can feel a bit overkill. In some cases, dev's just want to use the Model classes directly without a ViewModel step. Maybe in some future version of Mvx, then MvvmCross might add some alternative mechanism to allow DataBound UI elements to look outside of their own DataContext - this has been suggested in e.g. https://github.com/MvvmCross/MvvmCross/issues/35 - but today this doesn't exist (that I know of)

如果你没有要使用的ValueConverter路线,那么这样做的一种方式是使用一个ValueConverter上的ItemsSource - 例如,是这样的:

If you did want to use the ValueConverter route, then one way of doing this is to use a ValueConverter on the ItemsSource - for example, something like:

public class FooWrappingValueConverter : MvxValueConverter<IList<Foo>, IList<FooWithSelectionState>>
{
     protected override IList<FooWithSelectionState> Convert(IList<Foo> value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
     {
         var viewModel = parameter as MyViewModel;

         return value.Select(f => new FooWithSelectionState()
                                       {
                                          Foo = f,
                                          IsSelected = viewModel.IsSelected(f)
                                       })
                     .ToList();
     }
}

这可能与一名前pression像的ItemsSource FooWrapping结合使用(SOURCELIST,。) - 但是在动态的情况下使用这个(其中列表中要小心频繁的变化),因为这可能会很慢。

This could be used in binding with an expression like ItemsSource FooWrapping(SourceList, .) - but be careful using this in dynamic situations (where the list changes frequently) as this could be slow.

这篇关于如何列表项结合到它是否包含在另一个集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆