简体   繁体   中英

Xamarin.Forms ListView in Listview on Android

I want to add in my listview one more listview becouse i need show more info after selected item. If label is selected in my list, i would that more info show up below label and all list will go down

<ListView x:Name="ChallengeList" SeparatorColor="#3d122c" HasUnevenRows="True"
            ItemSelected="ChallengeList_ItemSelected"  RelativeLayout.YConstraint="{ConstraintExpression ElementName=Lab, Constant=0,Factor=1,Property=Height,Type=RelativeToView}"
      RelativeLayout.HeightConstraint="{ConstraintExpression Property=Height,Factor=0.8,Type=RelativeToParent}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal"  BackgroundColor="#40FFFFFF" Padding="10">
                            <StackLayout HorizontalOptions="CenterAndExpand">
                              <Label Text="{Binding Title}" TextColor="#ff3f50" FontSize="17" FontAttributes="Bold" HorizontalOptions="Center"/>
                            </StackLayout>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
           </ListView.ItemTemplate>
</ListView>

This is not recommended because the ListView has a scrolling function, hence 2 scroll views inside one another will cause issues. As such, I suggest you create a custom repeater control for this purpose.

Below is an example, taken from: https://github.com/velocitysystems/xf-controls/blob/master/XF.Controls/XF.Controls/Layouts/BindableStackLayout.cs

Create a new class, and enter this code.

namespace XF.Controls.Layouts
{
    using System.Collections.Generic;
    using Xamarin.Forms;

    /// <summary>
    /// A <see cref="StackLayout"/> that can be bound to a <see cref="DataTemplate"/> and data source.
    /// </summary>
    public class BindableStackLayout : StackLayout
    {
        #region Bindable Properties

        /// <summary>
        /// Property bound to <see cref="ItemTemplate"/>.
        /// </summary>
        public static readonly BindableProperty ItemTemplateProperty =
           BindableProperty.Create(
               propertyName: nameof(ItemTemplate),
               returnType: typeof(DataTemplate),
               declaringType: typeof(BindableStackLayout),
               defaultValue: default(DataTemplate),
               propertyChanged: OnItemTemplateChanged);

        /// <summary>
        /// Property bound to <see cref="ItemsSource"/>.
        /// </summary>
        public static readonly BindableProperty ItemsSourceProperty =
            BindableProperty.Create(
                propertyName: nameof(ItemsSource),
                returnType: typeof(IEnumerable<object>),
                declaringType: typeof(BindableStackLayout),
                propertyChanged: OnItemsSourceChanged);

        #endregion

        #region Properties 

        /// <summary>
        /// Gets or sets the <see cref="DataTemplate"/>.
        /// </summary>
        public DataTemplate ItemTemplate
        {
            get { return (DataTemplate)GetValue(ItemTemplateProperty); }
            set { SetValue(ItemTemplateProperty, value); }
        }

        /// <summary>
        /// Gets or sets the collection of view models to bind to the item views.
        /// </summary>
        public IEnumerable<object> ItemsSource
        {
            get { return (IEnumerable<object>)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        #endregion

        #region Property Changed Callbacks

        /// <summary>
        /// Called when <see cref="ItemTemplate"/> changes.
        /// </summary>
        /// <param name="bindable">The <see cref="BindableObject"/> being changed.</param>
        /// <param name="oldValue">The old value.</param>
        /// <param name="newValue">The new value.</param>
        private static void OnItemTemplateChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var layout = (BindableStackLayout)bindable;
            if (newValue == null)
            {
                return;
            }

            layout.PopulateItems();
        }

        /// <summary>
        /// Called when <see cref="ItemsSource"/> is changed.
        /// </summary>
        /// <param name="bindable">The <see cref="BindableObject"/> being changed.</param>
        /// <param name="oldValue">The old value.</param>
        /// <param name="newValue">The new value.</param>
        private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var layout = (BindableStackLayout)bindable;
            if (newValue == null)
            {
                return;
            }

            layout.PopulateItems();
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Creates and binds the item views based on <see cref="ItemTemplate"/>.
        /// </summary>
        private void PopulateItems()
        {
            var items = ItemsSource;
            if (items == null || ItemTemplate == null)
            {
                return;
            }

            var children = Children;
            children.Clear();

            foreach (var item in items)
            {
                children.Add(InflateView(item));
            }
        }

        /// <summary>
        /// Inflates an item view using the correct <see cref="DataTemplate"/> for the given view model.
        /// </summary>
        /// <param name="viewModel">The view model to bind the item view to.</param>
        /// <returns>The new view with the view model as its binding context.</returns>
        private View InflateView(object viewModel)
        {
            var view = (View)CreateContent(ItemTemplate, viewModel, this);
            view.BindingContext = viewModel;
            return view;
        }

        #endregion

        #region Static Methods

        /// <summary>
        /// Create UI content from a <see cref="DataTemplate"/> (or optionally a <see cref="DataTemplateSelector"/>).
        /// </summary>
        /// <param name="template">The <see cref="DataTemplate"/>.</param>
        /// <param name="item">The view model object.</param>
        /// <param name="container">The <see cref="BindableObject"/> that will be the parent to the content.</param>
        /// <returns>The content created by the template.</returns>
        public static object CreateContent(DataTemplate template, object item, BindableObject container)
        {
            var selector = template as DataTemplateSelector;
            if (selector != null)
            {
                template = selector.SelectTemplate(item, container);
            }

            return template.CreateContent();
        }

        #endregion
    }
}

Then in your page add

xmlns:controls="clr-namespace:XF.Controls.Layouts" 

<controls:BindableStackLayout ItemsSource="{Binding modelInHere}">
    <controls:BindableStackLayout.ItemTemplate>
        <DataTemplate>
            <!-- Your layout here -->
        </DataTemplate>
    <controls:BindableStackLayout.ItemTemplate>
</controls:BindableStackLayout>

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