0

I want to display a ListView and other controls inside a ScrollView. All is bound to a ViewModel. My attempts failed because it's not recommend to put a ListView inside a ScrollView. As I use a complex ViewCell DataTemplate, I did not consider to add my items in the code behind file as Buttons instead of a ListView.

Hope someone can show me a Xaml or CS pattern to achieve my goal.

Please only suggest a solution which works on iOS and Android!

Thanks

Eric

BytesGuy
  • 4,097
  • 6
  • 36
  • 55
Erich Brunner
  • 612
  • 5
  • 19
  • Please, show the code you are having problems with. Also, check my asnwer on this other question. It might be a duplicate of yours: http://stackoverflow.com/questions/38228008/xamarin-forms-two-listviews-stacked/38232920#38232920 – Rodrigo Elias Dec 12 '16 at 12:32
  • Thanks. This guy from your answered related question talks about to stacked ListViews. In have on top one ListView and below that ListView 10 Labels and one Button. All alignment is vertically. – Erich Brunner Dec 12 '16 at 12:55

2 Answers2

0

This is XAML code

<ScrollView Padding="2">
  <StackLayout HorizontalOptions="FillAndExpand">
    <Grid HorizontalOptions="FillAndExpand">
    <StackLayout>
    <ScrollView Orientation="Horizontal">
      <ListView BackgroundColor="Transparent" ItemsSource="{Binding UsersList}" SeparatorVisibility="None" x:Name="YourListView" RowHeight="50">
        <ListView.ItemTemplate>
          <DataTemplate>
            <ViewCell>
                <StackLayout  BackgroundColor="Transparent" Padding="5">
                    <Button Text="{Binding UserName}" WidthRequest="115" HorizontalOptions="FillAndExpand" TextColor="White" BackgroundColor="#4b76c4" FontAttributes="Bold" FontSize="20" FontFamily="Avenir Book"/>
                </StackLayout>
            </ViewCell>
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>
    </ScrollView>
    </StackLayout>
   </Grid>
  </StackLayout>
</ScrollView>

and .cs file you need set BindingContext

 BindingContext = new YourViewModel();
Mounika
  • 412
  • 2
  • 20
0

Solution:

As Rodrigo E suggested I download the latest Xamarin Evolve App 2016. After digging through the code I adjusted/simplified the FeedPage.xaml in the solution to that:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamarinEvolve.Clients.UI;assembly=XamarinEvolve.Clients.UI"
xmlns:pull="clr-namespace:Refractored.XamForms.PullToRefresh;assembly=Refractored.XamForms.PullToRefresh"
x:Class="XamarinEvolve.Clients.UI.FeedPage"
x:Name="FeedPage"
Title="Evolve Feed"
Icon="tab_feed.png"
BackgroundColor="{DynamicResource WindowBackgroundTable}">

<pull:PullToRefreshLayout
    IsPullToRefreshEnabled="True"
    RefreshCommand="{Binding RefreshCommand}"
    IsRefreshing="{Binding IsBusy}">
    <local:AlwaysScrollView
        HorizontalOptions="FillAndExpand"
        VerticalOptions="FillAndExpand">
        <StackLayout>

            <StackLayout Spacing="0">
                <local:NonScrollableListView
                    x:Name="ListViewSessions"
                    ItemsSource="{Binding Sessions}">
                  <local:NonScrollableListView.RowHeight>
                    <OnPlatform x:TypeArguments="x:Int32" Android="50" iOS="50" WinPhone="50"/>
                  </local:NonScrollableListView.RowHeight>
                    <local:NonScrollableListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <Button Text="{Binding Title}" BackgroundColor="Black" TextColor="Green" />
                            </ViewCell>
                        </DataTemplate>
                    </local:NonScrollableListView.ItemTemplate>
                </local:NonScrollableListView>
            </StackLayout>

            <StackLayout Padding="0" Spacing="0" BackgroundColor="Green">
                <Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
                <Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
                <Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
                <Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
                <Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
                <Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
            </StackLayout>

        </StackLayout>
    </local:AlwaysScrollView>
</pull:PullToRefreshLayout>

There are a few things to do:

  1. In the FeedViewModel.cs I added that code for a quick test:

       async Task ExecuteLoadSessionsCommandAsync()
    {
        if (LoadingSessions)
            return;
    
        LoadingSessions = true;
    
        try
        {
            NoSessions = false;
            Sessions.Clear();
            OnPropertyChanged("Sessions");
            #if DEBUG
            await Task.Delay(1000);
            #endif
            var sessions = await StoreManager.SessionStore.GetNextSessions();
    
            var testSessions = new List<Session>();
            testSessions.Add(new Session
            {
                Title = "TEST"
            });
    
            testSessions.Add(new Session
            {
                Title = "TEST"
            });
    
            testSessions.Add(new Session
            {
                Title = "TEST"
            });
    
    
            sessions = testSessions;
            if(sessions != null)
                Sessions.AddRange(sessions);
    
            NoSessions = Sessions.Count == 0;
        }
        catch(Exception ex)
        {
            ex.Data["method"] = "ExecuteLoadSessionsCommandAsync";
            Logger.Report(ex);
            NoSessions = true;
        }
        finally
        {
            LoadingSessions = false;
        }
    
    }
    
  2. You have to reference the package Refractored.XamForms.PullToRefresh to get the Pull-to-Refresh behavor. This is in that namespace referenced: xmlns:pull="clr-namespace:Refractored.XamForms.PullToRefresh;assembly=Refractored.XamForms.PullToRefresh"

  3. You have to Copy the AlwaysScrollView , NonScrollableListView to your PCL library. refercene it with: xmlns:local="clr-namespace:"

  4. In your iOS Project add that custom ListView Renderer:

    public class NonScrollableListViewRenderer : ListViewRenderer {

    protected override void OnElementChanged(ElementChangedEventArgs e) { base.OnElementChanged(e); if (Control != null) Control.ScrollEnabled = false;

    } }

    public class AlwaysScrollViewRenderer : ScrollViewRenderer { public static void Initialize() { var test = DateTime.UtcNow; } protected override void OnElementChanged(VisualElementChangedEventArgs e) { base.OnElementChanged(e); this.AlwaysBounceVertical = true; } }

See file: Renderer

  1. Put that CollectionChanged Handler in your Code-behind file:

    ViewModel.Sessions.CollectionChanged += (sender, e) => { var adjust = Device.OS != TargetPlatform.Android ? 1 : -ViewModel.Sessions.Count + 1; ListViewSessions.HeightRequest = (ViewModel.Sessions.Count * ListViewSessions.RowHeight) - adjust; };

See File FeedPage.cs.xaml: FeedPage.cs.xaml

Community
  • 1
  • 1
Erich Brunner
  • 612
  • 5
  • 19