Can I bind to a command from a ListView's parent when I'm using ViewCells in a separate file?

UnreachableCodeUnreachableCode USMember ✭✭✭
edited March 28 in Xamarin.Forms

My app needs to switch between two different ViewCells, so I've been using a DataTemplateSelector for this like so:

using MyOrg.PageModels;
using Xamarin.Forms;

namespace MyOrg.ViewCells
{
    public class ItemDataTemplateSelector : DataTemplateSelector
    {
        public ItemDataTemplateSelector()
        {
            // Retain instances 
            SimpleTemplate = new DataTemplate(typeof(SimpleItemViewCell));
            DetailedTemplate = new DataTemplate(typeof(DetailedItemViewCell));
        }

        protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
        {
            return ((MyPageModel)container.BindingContext).SimpleModeEnabled ? SimpleTemplate : DetailedTemplate;
        }

        private readonly DataTemplate SimpleTemplate;
        private readonly DataTemplate DetailedTemplate;
    }
}

The issue now is that when creating these cells in the constructor, it's using the ViewCells from separate files to the actual page:

 <ViewCell xmlns="http://xamarin.com/schemas/2014/forms" 
           xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
           x:Class="MyOrg.ViewCells.SimpleItemViewCell">
     <Frame CornerRadius="2.5"
             Margin="5, 2.5"
             Padding="10" >
         <StackLayout Orientation="Horizontal">
             <Label Text="{Binding Number}" 
                    TextColor="{StaticResource MidBlue}" 
                    FontSize="Large" />
             <Label Text="{Binding DetailText}" 
                    TextColor="Black" 
                    FontSize="Large" 
                    LineBreakMode="TailTruncation"/>
         </StackLayout>
     </Frame>
     <ViewCell.ContextActions>
         <MenuItem
                   Command="{Binding Path=ParentBindingContext.DeleteSelectedCommand, Source={x:Reference MyPageName}}"
                   Icon="sharp_delete_white_24.png"/>
     </ViewCell.ContextActions>
 </ViewCell>

MyPageName refers to the name of my page from a content page file. But I don't have access to this from this separate file, so the command doesn't fire.

Is there any way I can pass a reference to the page into each of these ViewCells?

Best Answer

Answers

  • UnreachableCodeUnreachableCode USMember ✭✭✭
    edited March 29

    @LandLu this works great. My command is now firing. I needed to pass the item into the command so that I could delete it. Here's what I came up with that built on your approach in the SimpleItemViewCell by overriding OnBindingContextChanged. I'm not sure if it's the best approach as I have to retain the cell and the menu item which seems a bit clumsy to me.

    static void ReferencedPageChanged(object bindableObject, object oldValue, object newValue)
    {
        if (newValue != null)
        {
            menuItem = new MenuItem();
            menuItem.Icon = "sharp_delete_white_24.png";
            menuItem.SetBinding(MenuItem.CommandProperty, new Binding("DeleteSelectedCommand", source: newValue));
    
            simpleViewCell = bindableObject as ViewCell;
        }
     }
    
     protected override void OnBindingContextChanged()
     {
         base.OnBindingContextChanged();
         if (BindingContext != null)
         {
             menuItem.SetBinding(MenuItem.CommandParameterProperty, new Binding("BindingContext", source: this));
             simpleViewCell.ContextActions.Add(menuItem);
         }
     }
    
Sign In or Register to comment.