Xamarin.Forms PullToRefresh not occuring when ListView is empty? - c#

In Xamarin.Forms I have a simple ListView that is bound to a view model using MVVM.
<ListView Grid.Row="1"
ItemsSource="{Binding ContactsGrouped}"
IsGroupingEnabled="true"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"
GroupDisplayBinding="{Binding Key}"
GroupShortNameBinding="{Binding Key}"
BackgroundColor="Transparent"
SelectionMode="Single"
HasUnevenRows="true"
SeparatorColor="#cccccc">
<ListView.ItemTemplate>
<cr:MyItemTemplate>
</ListView.ItemTemplate>
</ListView>
This is my xaml code, which works perfectly fine if the list has at least 1 item. By tapping and pulling down on the item, the list view refreshes fine, however tapping and pulling down outside of the item, the list does not cause PullToRefresh to occur. It's almost as if the ListView has transparent input but its items do not, thus allowing it to work.
Anything in the red in my example image shows the area where if I tap and drag down the activity indicator appears fine and the refresh happens. Tap and dragging anywhere in the green however causes the View to not refresh and the activity indicator to not appear.
I won't show my view model as the issue is with the View. I've also tried setting background color to red, checking if transparent was causing an issue, sadly that is not the case. Any ideas?

I just reproduced your problem on my side. After some researching, I found it is known issue from Xamarin.forms 3.5.0 and it still exist in Latest stable 3.6.0.344457.
The WorkAround is downgrade your Xamarin.forms version to 3.4.0.
Also, I test it in the Latest prerelease 4.0.0.394984-pre10 and it works well. So, I believe this issue will be solved in the next release version.
You can follow this issue to check the process.

Try adding VerticalOptions="StartAndExpand".
<ListView Grid.Row="1"
ItemsSource="{Binding ContactsGrouped}"
IsGroupingEnabled="true"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"
GroupDisplayBinding="{Binding Key}"
GroupShortNameBinding="{Binding Key}"
BackgroundColor="Transparent"
SelectionMode="Single"
HasUnevenRows="true"
SeparatorColor="#cccccc"
VerticalOptions="StartAndExpand">
<ListView.ItemTemplate>
<cr:MyItemTemplate>
</ListView.ItemTemplate>
</ListView>
This property tells the View how much space of your screen should it cover. If you don't add it then the View will just cover whatever the required length to display the data it needs.

Related

How to render x items in xamarin without scroll

Ok, this is a little strange, but I need to take a screenshot of a list of items in Xamarin. The problem is that I'm using a ListView and it only renders about 5 items. I need to render all elements in the list. I don't care if it's smaller on-screen; I just want to take a screenshot of the view and be able to share it.
This is my .xaml:
<BoxView HorizontalOptions="FillAndExpand" HeightRequest="0.5" Color="Gray"/>
<controls:CustomListView x:Name="list"
ItemsSource="{Binding List}"
HeightRequest="1000" VerticalOptions="Fill"
HasUnevenRows="True">
<x:Arguments>
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
</x:Arguments>
<controls:CustomListView.ItemTemplate>
<DataTemplate>
<cell:ItemViewCell></cell:ItemViewCell>
</DataTemplate>
</controls:CustomListView.ItemTemplate>
</controls:CustomListView>
<BoxView HorizontalOptions="FillAndExpand" HeightRequest="0.5" Color="Gray"/>
This is for Android.
In the code behind you something like this on the OnAppearing method
list.HeightRequested = list.ItemSource.Count * list.RowHeight;
you can also try to do the same thing on the CustomList's OnPropertyChanged where propertyName is ItemSource whatever feels best for you
I had to create pdf, it is not possible to "overlap" the boundaries of the screen, At least no with a List, I went the pdf way

Get Clicked Item in GridView within SemanticZoom

I have a very basic SemanticZoom implementation within my Windows 8 app. This app has the following xaml:
<SemanticZoom x:Name="semanticZoom" VerticalAlignment="Stretch" IsZoomedInViewActive="False">
<SemanticZoom.ZoomedOutView>
<GridView x:Name="myGridView" ItemsSource="{Binding Source={StaticResource orderViewSource}}" ScrollViewer.IsHorizontalScrollChainingEnabled="False" SelectionMode="None" IsItemClickEnabled="True" ItemClick="orderGridView_ItemClick">
</GridView>
</SemanticZoom.ZoomedOutView>
...
</SemanticZoom>
Oddly, the orderGridView_ItemClick event never fires when I click an item. I've heard that the semantic zoom control catches it, and doesn't bubble it down. If that's the case though, there should still be a way for me to see which item was selected. How do I determine what item an user clicks from the ZoomedOutView within a SemanticZoom control?
Thank you!

Building comment tree efficiently in Metro XAML

I am trying to build a 'comments control' (In a win8 XAML app, which is similar to Silverlight) which will load and render a comment tree for the user.
Each comment can have 0 or 1+ children comments (which recurses through each comment).
Each comment displays a set of info, including author, time, the comment itself, etc.
The approach I initially took to build this is to use a ListView which has a 'CommentItem' control binding.
<TextBlock Grid.Row="1" TextWrapping="Wrap" Text="{Binding commentText}" FontSize="11" FontFamily="Global User Interface" />
<ListView Grid.Row="2" x:Name="CommentRepliesList" ItemsSource="{Binding}" >
<ListView.ItemTemplate>
<DataTemplate>
<local:CommentItem Tag="{Binding}"></local:CommentItem>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The above will just recurse through each comment, apply the comment text, and then create a new commentitem for each comment child, recurse through again, etc.
The issue, however, is this is extremely slow and non-performant.
Does anyone know a more efficient way to do this? Is ListView the appropriate control to use for this?

How to combine Semantic Zoom and Listbox for Snapped View

I have a Grouped Items Page created from VS11 template. This page has a GridView for normal view and a ListView that is shown when the page is snapped. I need to implement Semantic Zoom and still be able to snap the page.
I tried moving the GridView SemanticZoom.ZoomedInView so I have
<ScrollViewer x:Name="itemListScrollViewer" ...
<Listview ...
</ScrollViewer>
<SemanticZoom Grid.Row="1" >
<SemanticZoom.ZoomedInView>
<GridView ...
</SemanticZoom.ZoomedInView>
</SemanticZoom>
When the page is not snapped the ListView is hidden and when the page is snapped the gridView is hidden. The problem is that in snapped view the ListBox does not scroll and does not react to item clicks.
Do you want the snapped view to also have semantic zoom? In those cases, what I have done is implement two different SemanticZooms, one for landscape and one for snapped, and then showed only the correct one for current visual state. So starting point would be this:
<SemanticZoom x:Name="semanticZoom" Visibility="Visible">
<SemanticZoom.ZoomedOutView>
<GridView ...
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<GridView ...
</SemanticZoom.ZoomedInView>
</SemanticZoom>
<SemanticZoom x:Name="semanticZoomSnapped" Visibility="Collapsed">
<SemanticZoom.ZoomedOutView>
<ListView ...
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<ListView ...
</SemanticZoom.ZoomedInView>
</SemanticZoom>
Or if you don't need semantic zoom in the snapped mode, just try your current approach but try hiding the SemanticZoom element instead of the GridView inside it. And of course make sure that ListView's isItemClickEnabled is set to true etc.
P.S. I suppose where you say ListBox you mean ListView? Since an element called ListBox also exists.
I found a very strange way to fix the problem. When I switch the ordet of SemanticZoom an ScrollViewer like
<SemanticZoom Grid.Row="1" >
<SemanticZoom.ZoomedInView>
<GridView ...
</SemanticZoom.ZoomedInView>
</SemanticZoom>
<ScrollViewer x:Name="itemListScrollViewer" ...
<Listview ...
</ScrollViewer>
Than everything works. Any idea why?

Silverlight: Layout changes when I call NavigationService.Navigate

This is a really weird bug. I have no idea why it could be happening. I know that posting it here is a bit of a long-shot, but I'm out of other ideas.
I have two ListBoxs that act as menus.
<ListBox Margin="56,8,15,0" FontSize="64"
ItemsSource="{Binding FavoriteSections}"
SelectionChanged="MenuList_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Remove" Click="FavoritesContextMenuItem_Click" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<TextBlock Text="{Binding DisplayName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox x:Name="sectionList" Margin="56,8,15,0" FontSize="64"
SelectionChanged="MenuList_SelectionChanged"
ItemsSource="{Binding SectionViewModels}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Add to favorites" Click="SectionContextMenuItem_Click" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<TextBlock Text="{Binding DisplayName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The bug exists across both of them.
When the selection changes on either menu, this method is called:
void MenuList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 0)
{
return;
}
Uri page = null;
object selected = e.AddedItems[0];
if (selected is NavigableItem)
{
NavigableItem selectedItem = (NavigableItem)selected;
page = selectedItem.Page;
}
else if (selected is SectionViewModel)
{
SectionViewModel selectedVM = (SectionViewModel)selected;
page = selectedVM.Section.Page;
}
Debug.Assert(page != null, "What is the type of `selected`?");
// if I comment out this line, the problem goes away:
NavigationService.Navigate(page);
ListBox selectedBox = (ListBox)sender;
selectedBox.SelectedIndex = -1;
}
If I comment out the NavigationService.Navigate() line, the problem goes away. If I replace the line with a different URI, the problem remains.
About 70% of the time, when I click on a menu item, the content jumps all over the page. (The remaining 30%, no bug occurs.) It happens too quickly to see what's really going on, but different UI elements overlap each other.
This only occurs the first time I click on something in those menus during the app's lifetime. If I hit "back" then select a menu item again, the problem will not occur.
What could be happening here? I really have no idea. The code-behind doesn't have a OnNavigatedFrom method, so I don't think it's a problem there.
I'm using Silverlight for Windows Phone 7
Update: Mysteriously, I can't seem to reproduce this in the debugger - only after deploying the app and running it in the emulator unattached. ???
Update 2: The bug appears when NavigationService.Navigate() is called from the Click event handler of a button, as well:
<Button Content="Foo" Click="Button_Click" Grid.Row="0"/>
private void Button_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/Views/sections.xaml?section=43", UriKind.Relative));
}
Looks like the bug has to do with the navigation, not the UI element used to trigger the call.
Update 3: More weirdness. Still not able to reproduce the app while the debugger is attached. If I make the loading progress bar always collapsed, the bug disappears:
<ProgressBar x:Name="LoadingProgressBar"
IsIndeterminate="True"
Visibility="Collapsed"
Style="{StaticResource PerformanceProgressBar}"
VerticalAlignment="Top"/>
Alternatively, commenting out this line in code-behind makes the bug disappear:
LoadingProgressBar.Visibility = Visibility.Collapsed;
I really don't understand what's going on here. That line of code is not executed when the page is navigated from.
Here is the full XAML of the control that's getting messed up:
<ProgressBar x:Name="LoadingProgressBar"
IsIndeterminate="True"
Visibility="Collapsed"
Style="{StaticResource PerformanceProgressBar}"
VerticalAlignment="Top"/>
<TextBlock x:Name="DownloadFailed"
Visibility="Collapsed"
Style="{StaticResource disabledText}"
Margin="56,8,8,-8" >
FooBar.com could not be reached. Do you have a network connection?
</TextBlock>
<ListBox x:Name="sectionList" Margin="56,8,15,0" FontSize="64"
SelectionChanged="MenuList_SelectionChanged"
ItemsSource="{Binding SectionViewModels}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Add to favorites" Click="SectionContextMenuItem_Click" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<TextBlock Text="{Binding DisplayName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</controls:PivotItem>
The problem lies in your usage of the Indeterminate ProgressBar. All its animations are done on the UI thread, and not the Compositor thread, as is the usual practise. Since you are already using the Windows Phone Toolkit, you can easily replace your ProgressBar with the PerformanceProgressBar offered by the toolkit. This should solve your problems.
Before I begin, let me say that I don't have a lot of experience with Windows Phone, so my answers are based on more generic WPF knowledge, so forgive me if I'm overlooking specifics of the platform, or am referencing features not available.
Some diagnostic questions (sorry this isn't a direct answer):
Firstly, it does seem like Navigate is calling a lot of layoutUpdates. I haven't yet seen what type of container is containing the pages you're updating, but it is worth asking, is that also being disrupted or only the menus?
Secondly, could you try specifying your itemPanel explicitly? You're expecting them to be virtualizingStackPanels, but you may find that some parent object in your visual hierarchy is creating a different inheritance scenario.
You have these in a grid, which is meant to size to its content, or take the default size (100x100 in normal WPF) or take sizing from its parent, which without knowing how you've specified the grid, or the grid's parent, it's difficult to know its behaviour. Furthermore, Grids automatically z-order their children according to the order in which they were added. Can you determine whether it is just the layout of the lisboxes that is being disturbed, or whether it is the entire grid? Or, is it larger than that?
If you attach to the layoutUpdated() event of the listboxes, grid, or grid's parent, you should be able to look at the stacktraces that lead you there - it sounds to me that you'll find that layoutUpdated() is firing more than you'd like it to. Further, you'll be able to output the heights and widths (ActualHeight etcetera of course) during those steps so that you can see when exactly those changes happen.
I hope that some of these diagnostic steps might help you reach an answer.

Categories

Resources