0

Hi I want to use the BindingContext property to bind different ViewCell to my Listview based on a certain condition

Here is the Xaml

<ListView>
    <ListView.ItemTemplate>
                  <DataTemplate>
                        <ViewCell BindingContext="??">//What do I do here?
                        </ViewCell>
                  </DataTemplate>
        </ListView.ItemTemplate>
 </ListView>

Here is are the classes for the ViewCells

    public class textViewCellNoContextActions : ViewCell
    {
        public textViewCellNoContextActions()
        {
            StackLayout layout = new StackLayout();
            layout.Padding = new Thickness(15, 0);
            Label label = new Label();

            label.SetBinding(Label.TextProperty, "ListItemTitle");
            layout.Children.Add(label);
            View = layout;
        }
    }

public class textViewCellWithContextActions : ViewCell
{
    public textViewCellWithContextActions()
    {
        StackLayout layout = new StackLayout();
        layout.Padding = new Thickness(15, 0);
        Label label = new Label();

        label.SetBinding(Label.TextProperty, "ListItemTitle");
        layout.Children.Add(label);

        var moreAction = new MenuItem { Text = "More" };
        moreAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
        moreAction.Clicked += OnMore;

        var deleteAction = new MenuItem { Text = "Delete", IsDestructive = true }; // red background
        deleteAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
        deleteAction.Clicked += OnDelete;

        this.ContextActions.Add(moreAction);
        this.ContextActions.Add(deleteAction);
        View = layout;
    }

In my ViewModel, I want to decide which ViewCell to bind to. How do I achieve this? Do I also need to use BindingContextChanged?

Andrii Krupka
  • 4,276
  • 3
  • 20
  • 41
stepheaw
  • 1,683
  • 3
  • 22
  • 35
  • Why would you want to have an item in your list bound to something other than an item in the list's source? That seems like it defeats the purpose of having a databound list. – Jason Jun 29 '16 at 21:41

3 Answers3

2

You want to use a DataTemplateSelector for this - you aren't really changing the Binding context of each cell as much as you are changing the visual Cell that gets used. The ListView itself will be in control of those Binding contexts.

https://blog.xamarin.com/customizing-list-view-cells-xamarin-forms-datatemplateselector/

Keith Rome
  • 3,208
  • 19
  • 15
  • Thank you for your help, I looked into the DataTemplateSelector and it looks like a good solution to my problem. I found another way to do this by using 'BindingContextChanged' on the ViewCell. What I really wanted to achieve by this, was to add or remove ContextActions based on a certain condition – stepheaw Jul 01 '16 at 15:33
  • I see, yes that's a valid way of doing it and I've done it myself for exactly that use case before as well. – Keith Rome Jul 01 '16 at 21:28
2

For what I wanted to achieve I did the following...

In the XAML

<ViewCell BindingContextChanged="OnBindingContextChanged">

In the code behind

private void OnBindingContextChanged(object sender, EventArgs e)
{
    base.OnBindingContextChanged();

    if (BindingContext == null)
        return;

    ViewCell theViewCell = ((ViewCell)sender);
    var item = theViewCell.BindingContext as ListItemModel;
    theViewCell.ContextActions.Clear();

    if (item != null)
    {
        if (item.ListItemType == ListItemTypeEnum.FavoritePlaces
           || item.ListItemType == ListItemTypeEnum.FavoritePeople)
        {
            theViewCell.ContextActions.Add(new MenuItem()
            {
                Text = "Delete"
            });
        }
    }
}

Based which type of list item we are dealing with, we get to decide where to place the context actions

stepheaw
  • 1,683
  • 3
  • 22
  • 35
  • this code make app crash in android platform please check my question https://stackoverflow.com/questions/47618834/xamarin-forms-strange-behavior-when-implementing-bindingcontextchanged-event – Mina Fawzy Dec 03 '17 at 14:58
  • 1
    Dude don't down vote my answer. You're probably using an android device that is that gives you a NPE because LongPress is not implemented on that device. Use a different API version. This would be a xamarin Bug – stepheaw Dec 04 '17 at 18:58
  • 2
    I confirmed myself. Code not crushing as @stepheaw said. – PilgrimViis Jan 25 '18 at 11:55
0

You can directly use the properties in the ViewCell's elements, like below. BindingContext is not required for ViewCell.

<ListView ItemsSource="{Binding Attachments}">
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <StackLayout>
          <Label Text="{Binding Name}" />
          <Image Source="{Binding FilePath}"/>
        </StackLayout>
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

Just make sure not to use ViewCell.View as child element of ViewCell.

This approach should work even if you have a subclass or custom class for your ViewCell.

Prabu Arumugam
  • 1,929
  • 2
  • 15
  • 19