简体   繁体   中英

MvvmCross vnext: monodroid CommandParameter similar to wp7

I use a Dictionary instead of a List in the MainMenuView from Tutorial sample. In wp7, I bind like this:

 <ListBox ItemsSource="{Binding Items}" x:Name="TheListBox">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Key}" Margin="12" FontSize="24" TextWrapping="Wrap">
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="Tap">
                                <commandbinding:MvxEventToCommand Command="{Binding Path=DataContext.ShowItemCommand, ElementName=TheListBox}" CommandParameter="{Binding Value}" />
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

But with monodroid, I don't know where to put CommandParameter="{Binding Value}" in mvxListView, I get this error:"MvxBind:Error: 2,71 Problem seen during binding execution for from Items to ItemsSource - problem ArgumentException: failed to convert parameters" from my axml code:

<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"

/>

How can I set a CommandParameter property as in wp7 ?

Thanks in advance for your help.

Following your instruction 1, I change MainMenuViewModel in Tutorial.Core like this:

`public Dictionary Items { get; set; }

    public ICommand ShowItemCommand
    {
        get
        {
            return new MvxRelayCommand<KeyValuePair<string, Type>>((type) => DoShowItem(type.Value));
        }
    }

    public void DoShowItem(Type itemType)
    {
        this.RequestNavigate(itemType);
    }

    public MainMenuViewModel()
    {
        Items = new Dictionary<string, Type>()
                    {
                        {"SimpleTextProperty",  typeof(Lessons.SimpleTextPropertyViewModel)},
                        {"PullToRefresh",  typeof(Lessons.PullToRefreshViewModel)},
                        {"Tip",  typeof(Lessons.TipViewModel)},
                        {"Composite",typeof(Lessons.CompositeViewModel)},
                        {"Location",typeof(Lessons.LocationViewModel)}
                    };
    }`

The sample is working as expected in wp7, but with monodroid I get the same error as the previous one because I think KeyValuePair Key property cause the problem in:

<LinearLayout
        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="wrap_content"
          android:layout_margin="12dp"
        android:orientation="vertical">
<TextView
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="View Model:"
        />
  <TextView
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textAppearance="?android:attr/textAppearanceLarge"
          local:MvxBind="{'Text':{'Path':'Key'}}"
        />
</LinearLayout>

Mvx doesn't currently have a separate CommandParameter dependency target so you can't currently tackle this problem in the same way.

The reason why CommandParameters aren't included is a design choice, and is tied to the lack of Behaviours. Because there isn't a behaviour object wrapping the command and the commandparameter together around a control event, then separate CommandParameter bindings would be needed for Click, LongClick, Swipe, etc. - and these could get quite verbose and ugly - so, so far, we've steered clear of this approach.

However, there are a couple of ways that you can achieve a similar effect to the one you are looking for.


Firstly, the ItemClick event on a list is always bound so that the parameter is always the object that has been clicked - so if you can do the .Value projection within your MvxRelayCommand action, then the code will work both in WP7 and in MonoDroid.

ie this can be achieved:

<ListBox ItemsSource="{Binding Items}" x:Name="TheListBox">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Key}" Margin="12" FontSize="24" TextWrapping="Wrap">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Tap">
                            <commandbinding:MvxEventToCommand Command="{Binding Path=DataContext.ShowItemCommand, ElementName=TheListBox}" CommandParameter="{Binding}" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </TextBlock>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

using:

<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"
/>

where your command handler does the .Value work:

public ShowItemCommand { get { return new MvxRelayCommand( item => { DoShowFor(item.Value); } ); } }


Secondly, you can instead choose to bind to the Click event on Views/Controls within each list Item, rather than binding to the List-level event. For some discussion of this, see the answers on MVVMCross changing ViewModel within a MvxBindableListView


Thirdly, you could write your own binding in this case if you really wanted to... I think that would be overkill for this situation, but it might be useful in other cases.


For more list selection examples, check out the BestSellers and CustomerManagement examples.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM