DataTemplate with TemplateSelector - bind to parent command

MJoehlMJoehl USMember ✭✭

Hi all

I have a ListView with a TemplateSelector and two different DataTemplates (ViewCells). Behind the ListView is a ViewModel for the ConentPage with an ObservableCollection which contains some item-models. The Binding to this Item-Model in my templates work like a charm.

What I want: My ContentPage-ViewModel has some commands. The DataTemplate should use this command. How can I bind to this commands?

I know, that I can make the commands static and reference with x:Static to it. Or I can add the Command to my Item-Model. But both are no Option for my solution.

Thanks in advance

Best Answer

Answers

  • jiangzhiyijiangzhiyi USMember

    thanks for @MichaelJhl,you are great!

  • RianDutraRianDutra USMember ✭✭

    @MJoehl how can I do it with XAML?

    I tried the code below but it didn't work:

    <Button Text="Test"
          Command="{Binding Path=ParentBindingContext.OpenCommand, Source={x:Reference MainPage}}"
          CommandParameter="{Binding .}" />
    
  • LippelLippel DEMember ✭✭

    It does work, thanks alot!

    But I found one downside: You cant use CachingStrategy="RecycleElement" on the listview if you use this custom view cell :(

    Any thoughts on that?

  • StinkyTowelStinkyTowel USMember ✭✭

    @MichaelJhl, did you inherit from BaseTemplate for your datatemplates? When I do, I get Error CS0260: Missing partial modifier on declaration of type 'SomeDataTemplate'; another partial declaration of this type exists.

  • StinkyTowelStinkyTowel USMember ✭✭

    I was able to get this going and it works very well (code behind and xaml), thanks @MichaelJhl for sharing!

  • Liger_JeromeLiger_Jerome FRUniversity ✭✭

    Hi !

    Thanks for this tip, in theory I'm agree with it... but impossible to make it works on my side :-(

    First, in your override "DataTemplate OnSelectTemplate", you can't create a new DataTemplate for each row... because on Android you will reach the "23 template count limit"... and I don't use RecycleElement as @Lippel suggested

    So this is my code

    'public class CheckItem_DatatemplateSelector : DataTemplateSelector
    {
    DataTemplate Acceptedtemplate { get; set; }
    DataTemplate Refusedtemplate { get; set; }
    DataTemplate Uncheckedtemplate { get; set; }

        protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
        {
            if (((CheckablePacketItem)item).IsChecked)
            {
                if (((CheckablePacketItem)item).IsAccepted)
                {
                    if (Acceptedtemplate == null)
                    {
                        Acceptedtemplate = new DataTemplate(typeof(CkeckItem_accepted));
                    }
                    Acceptedtemplate.SetValue(BaseItem.ParentBindingContextProperty, container.BindingContext);
                    return Acceptedtemplate;
                }
                else
                {
                    if (Refusedtemplate == null)
                    {
                        Refusedtemplate = new DataTemplate(typeof(CheckItem_refused));
                    }
                    Refusedtemplate.SetValue(BaseItem.ParentBindingContextProperty, container.BindingContext);
                    return Refusedtemplate;
                }
            }
            else
            {
                if (Uncheckedtemplate == null)
                {
                    Uncheckedtemplate = new DataTemplate(typeof(CheckItem_unchecked));
                }
                Uncheckedtemplate.SetValue(BaseItem.ParentBindingContextProperty, container.BindingContext);
                return Uncheckedtemplate;
            }
        }'
    

    The binding seems to work.

    But in my "CkeckItem_accepted" (or in the two other templates too), I try to bind a button with my "ParentBindingContext.m_CallExpCommand" and I don't know why but the command is never executed...

    ''

    Does anybody that has made this tips working, can post a complete sample ? (or help if you see errors...)

    Thanks in advance

  • KlimovGlebKlimovGleb RUMember
    edited October 2018

    @RianDutra Insted of ParentBindingContext u should use BindingContext.

  • UnreachableCodeUnreachableCode USMember ✭✭✭

    Is RecycleElementAndDataTemplate a suitable fix to the issue @Lippel and @Liger_Jerome mention?

    "The RecycleElementAndDataTemplate caching strategy builds on the RecycleElement caching strategy by additionally ensuring that when a ListView uses a DataTemplateSelector to select a DataTemplate, DataTemplates are cached by the type of item in the list. Therefore, DataTemplates are selected once per item type, instead of once per item instance."

  • LippelLippel DEMember ✭✭
    edited March 28

    @UnreachableCode
    Quite some time passed since I added my comment.
    I believe RecycleElementAndDataTemplate didnt exist at that time. You should give it a try, it seems very promising.

  • Liger_JeromeLiger_Jerome FRUniversity ✭✭

    Hum... yes there was some time passed ...

    But I remember that I finally got this working (and this is in production since months)

    Opening the source-code (my memory is failing), I can see that :

    • My Listview CachingStrategy is set to "RecycleElement"
    • My Listview ItemTemplate is set to my DataTemplateSelector
    • All my differents DataTemplates (used in my datatemplateSelector) inherits from a "BaseViewCell" where I have created a Bindable Property (to keep the "parentBindingContext of the cell/myPageViewModel" for triggering a Command (of my PageViewModel) on an item button click(with a property of the item as parameter of the command)

    If you want some sample code, MP-me

  • UnreachableCodeUnreachableCode USMember ✭✭✭

    Hm, I'm getting a pretty big performance hit when set to RecycleElementAndDataTemplate. I'm not sure I can use this. Will I have problems if I leave it set to RetainElement?

Sign In or Register to comment.