简体   繁体   中英

Xamarin Forms Bind command outside ItemSource

I have a problem. I created this ListView:

<ListView ItemsSource="{Binding knownDeviceList}" SelectionMode="None" RowHeight="90" ItemTapped="device_Clicked">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <ViewCell.ContextActions>
                    <MenuItem Command="{Binding DeleteDevice}"
            CommandParameter="{Binding Id}"
            Text="Delete" IsDestructive="True" />
                </ViewCell.ContextActions>

            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

The ListView is bound to a List with objects in it, but I need to bind the command to an ICommand outside the List on root level of the ViewModel. How can I do that, because now the ICommand doesn't get triggered when I try to remove an item from the List!

Here is my Command in my ViewModel:

public ICommand DeleteDevice
{
    get
    {
        return new Command<int>((x) => RemoveDevice_Handler(x));
    }
}

What am I doing wrong?

Your MenuItem.BindingContext is scoped to the actual item in that cell, not the view model of the whole page (or ListView ). You will either need to tell the binding that it needs to looks else where, like this:

<ListView x:Name="MyListView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <ViewCell.ContextActions>
                    <MenuItem Command="{Binding Path=BindingContext.DeleteDevice, Source={x:Reference MyListView}}}"/>
                </ViewCell.ContextActions>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Note that I removed the attributes that you have in there just to make clear which ones I added. You can keep them in, this is just for readability.

Or, you can use the new Relative Bindings . Then you would implement the command binding like this:

Command="{Binding Source={RelativeSource AncestorType={x:Type local:YourViewModelClass}}, Path=DeleteDevice}"

The Context that you are trying to bind with from the Command is not the Page 's one but the ItemSource , This is why you can simply bind the Id to the CommandParameter .

To fix this, you need to target the page's BindingContext since your Command lives at the ViewModel root level. You can achieve it by adding a x:Name property to your ListView and target the right Context through it.

Here the fix:

<ListView x:Name="listView" ItemsSource="{Binding knownDeviceList}" SelectionMode="None" RowHeight="90" ItemTapped="device_Clicked">
<ListView.ItemTemplate>
    <DataTemplate>
        <ViewCell>
            <ViewCell>
                <ViewCell.ContextActions> 
                    <MenuItem Command = "{Binding BindingContext.DeleteDevice, Source={x:Reference listView}}"
                        CommandParameter="{Binding Id}"
                        Text="Delete" IsDestructive="True"  />
                </ViewCell.ContextActions>
            </ViewCell>
        </ViewCell>
    </DataTemplate>
</ListView.ItemTemplate>

Hope it helps & happy coding!

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