3
votes

This is the situation:

I have a datasource that gets filtered by certain attribute (lets call it Checked), into two lists on the viewmodel. Call it New and Old.

New one needs to be displayed into one list, Old one needs to be displayed into the list right under it.

Oh and they need to scroll in unison. So if Old is currently out of screen, it will swim into visibility as the list is swiped up.

I've currently solved this with LongListSelectors like this:

<ScrollViewer  VerticalAlignment="Top" VerticalScrollBarVisibility="Auto">
    <StackPanel>
        <phone:LongListSelector x:Name="NewList" Margin="0,0,0,0" ItemsSource="{Binding New}"  SelectionChanged="NewList_SelectionChanged">
            <phone:LongListSelector.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="0,0,0,17">
                        <TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" Foreground="{Binding Color}" />
                    </StackPanel>
                </DataTemplate>
            </phone:LongListSelector.ItemTemplate>
        </phone:LongListSelector>
        <phone:LongListSelector x:Name="OldList" Margin="0,0,0,0" ItemsSource="{Binding Path=Old}" Padding="0,20,0,0">
            <phone:LongListSelector.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="0,0,0,17">
                        <TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" FontStyle="Italic" Foreground="{Binding Color}"/>
                    </StackPanel>
                </DataTemplate>
            </phone:LongListSelector.ItemTemplate>
        </phone:LongListSelector>
    </StackPanel>
</ScrollViewer>

Two longlistselectors inside a stackpanel inside a scrollviewer. Now it all works absolutely fab while there's something in both of those lists.

However, when one of them has no content whatsoever, it immediately expands to fill the entire height of its parent. In this case... the infinite scrollviewer. Which means that if there's nothing in the New list, there will be absolutely nothing visible on the screen whatsoever and if there's nothing on the New list... I can pretty much scroll infinitely after getting past the New list items.

Do I have any options here? Without programmatically creating a ton of Text fields and then trying to attach events to it, or worse, write my own list control? Standard listboxes don't work because they both scroll separately.

Any ideas?

2
Is there no MaxHeight property for the phone? I know sometimes it's kinda lame solution for WPF, but hell it works! - Hannish
There is. The problem is, that I can either scroll down too far or it doesn't expand enough. - NeroS
i have also similar kind of issue. Can you try to remove Scrollviewer which you explicitly defined and use thw default scrolling of ItemSelector. - D J

2 Answers

0
votes

Having two list controls under each other is a genrally a bad idea, because of ScrollViewers inside ScrolViewers.

I would advise you to use a single LongListSelector without any ScrollViewer around it. Then create a single collection with old an new items and use an ItemTemplateSelector to style them differently.

0
votes

The problem you are facing is that by the default when emty LLS is measured it's height as you see is 'infinite'. You are using StacPanel which means that second LLS is under infinite LLS.

The simples solution is to set the Height of LLS:

<phone:LongListSelector x:Name="NewList" Height="300" Margin="0,0,0,0" ItemsSource="{Binding New}"  SelectionChanged="NewList_SelectionChanged">

If you can - use a Grid with defined rows instead of StacPanel. If you still want to use StackPanel, you can override the method MeasureOverride() in LLS and make extension.
It should work if you do it like this:

namespace Extensions
{
   public class LongListSelectorEx : LongListSelector
   {
      protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
      {
         if (this.ItemsSource == null)
            return new System.Windows.Size(this.Width, 0);
         if (this.ItemsSource.Count <= 0)
            return new System.Windows.Size(this.Width, 0);

         return base.MeasureOverride(availableSize);
      }
   }
}

Watch out also if you haven't got width defined (the return value cannot be NaN - in that situation put 0 instead this.Width). Of course you will also need to check Height of LLS, bacause if you don't your controls can be pushed off the screen, when there are many items in LLS.
You can also read about this here