ScrollViewer.ChangeView() does not scroll horizontally - c#

I'm trying to create two scrollviewers that scroll vertically and horizontally respectively.
The scrolling should start when the manipulationdelta event is detected, and I have used the ChangeView method to move the scrollviewers accordingly. The vertical scrollviewer is ok, but it's not the same for the horizontal one.
I have added an image to show the 2 scrollviewers since i cannot post it right here.
Here's the code: XAML
<!--horizontal scrollviewer-->
<ScrollViewer x:Name="horizontalScrollViewer"
Grid.Column="1"
Grid.RowSpan="3"
HorizontalScrollMode="Disabled"
VerticalScrollMode="Disabled">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="100"/>
<RowDefinition Height="80"/>
</Grid.RowDefinitions>
<!--upperGrid-->
<GridView Grid.Row="0"
ScrollViewer.HorizontalScrollMode="Disabled"
ScrollViewer.VerticalScrollMode="Disabled"
ItemsSource="{Binding dataItems}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical"
MaximumRowsOrColumns="1"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock Height="80" Width="80" Text="{Binding}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<!--bottomGrid-->
<GridView Grid.Row="2"
ScrollViewer.HorizontalScrollMode="Disabled"
ScrollViewer.VerticalScrollMode="Disabled"
ItemsSource="{Binding dataItems}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical"
MaximumRowsOrColumns="1"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock Height="80" Width="80" Text="{Binding}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</ScrollViewer>
and the .cs
private void dataGrid_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var x = e.Delta.Translation.X;
var y = e.Delta.Translation.Y;
if(Math.Abs(x)> Math.Abs(y))
{
bool result = horizontalScrollViewer.ChangeView( horizontalScrollViewer.HorizontalOffset - x , null, null);
result = centralScrollViewer.ChangeView(horizontalScrollViewer.HorizontalOffset - x, null, null);
}
else
{
bool result = centralScrollViewer.ChangeView(null, verticalScrollViewer.VerticalOffset -y, null);
verticalScrollViewer.ChangeView(null, verticalScrollViewer.VerticalOffset - y, null);
}
}
In the msdn documentation I have read that :
horizontalOffset
Type: IReference [C++] | System.Nullable [.NET]
A value between 0 and ScrollableWidth that specifies the distance the content >should be scrolled horizontally.
but my ScrollableWidth is equal to zero and I can't understand why.
Does anyone know what's wrong with my code?

I've found a solution by myself!
I had to add the horizontalscrollbar visibility option on the horizontal scrollviewer. It's quite odd since I didn't need to add it to the vertical one. Anyway here's the code of the horizontal scrollviewer:
<ScrollViewer x:Name="horizontalScrollViewer"
Grid.RowSpan="3"
Grid.Column="1"
HorizontalScrollMode="Disabled"
HorizontalScrollBarVisibility="Auto"
VerticalScrollMode="Disabled">

I don't think you can scroll while scrolling is disabled. If you're just trying to hide the scrollbars, then do the following:
<ScrollViewer x:Name="horizontalScrollViewer"
Grid.Column="1"
Grid.RowSpan="3"
HorizontalScrollMode="Enabled"
VerticalScrollMode="Enabled"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden">
...
</ScrollViewer>

Related

GridView item height is fixed

I am working on a project where I have a GridView and I need to show an image and 3 TextBlocks. The image has a fixed Height and Width properties and the first TextBlock have either 1 line of text or 2. The other TextBlocks have only 1 line of text.
The problem is that if the first TextBlock has 1 line of text everything is shown perfectly but if the text is longer than one line the last TextBlock is not shown in the GridViewItem and it is pushed down where it gets hidden.
<GridView ItemsSource="{Binding HomeList, Mode=OneWay}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate x:DataType="local:ItemHelper">
<UserControl>
<StackPanel>
<Image Name="image" Source="{x:Bind ItemImage}"
Height="144" Width="256" HorizontalAlignment="Center"/>
<TextBlock Name="title" Text="{x:Bind ItemTitle}" Style="{StaticResource OneLinedItemTitle}"/>
<TextBlock Name="section" Text="{x:Bind ItemSection}"/>
<TextBlock Name="pubUpdate" Text="{x:Bind ItemPublishTime}"/>
</StackPanel>
</UserControl>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
I have also tried the above XAML with RelativePanel and the same thing happens. I want the height to be fixed at max height with 2 lines of text for title or adjustable for each item in the GridView.
As you can see that the first item shows 3 TextBlocks but the 2nd item shows only 2 where the first one has 2 lines of text.
I only see the following possible options:
Set the height of the StackPanel to be fixed for the max height of the items
Set the height of the title to be fixed with 2 lines of text
Maybe editing the default Style for GridViewItem would help
Or maybe there is any other possible option which doesn't involve setting the fixed height for any element.
Any suggestions? Thanks.
Why don't you use a Grid inside your UserControl instead of the StackPanel. The StackPanel sizes to content Heights only. I would use a Grid, set the RowDefinition at third Row to Height="*" and the other ones to Height="Auto". I tested this with an ItemsControl (that worked...)
<GridView ItemsSource="{Binding HomeList, Mode=OneWay}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate x:DataType="local:ItemHelper">
<UserControl>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Grid.Row="0" Name="image" Source="{x:Bind ItemImage}" Height="144" Width="256" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" Name="title" Text="{x:Bind ItemTitle}" Style="{StaticResource OneLinedItemTitle}"/>
<TextBlock Grid.Row="2" Name="section" Text="{x:Bind ItemSection}" TextWrapping="Wrap"/>
<TextBlock Grid.Row="3" Name="pubUpdate" Text="{x:Bind ItemPublishTime}"/>
</Grid>
</UserControl>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
It seems the first item is not rendering correctly (at least this is what happened to me). Check Justin XL answer, maybe it can help. Apparently the problem (from poor rendering) is solved by setting the ItemHeight property
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid ItemHeight="DesiredHeight"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>

White gap on orientation != portrait flat

My UWP App displays a white gap when the mobile device orientation is rotated to left or right.
My XAML:
<prismMvvm:SessionStateAwarePage>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ListBox Grid.Row="0" x:Name="VideoItemsListBox">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding title}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<MediaElement x:Name="VideoPlayer" Grid.Row="1">
</MediaElement>
</Grid>
Do I need to implement something to remove the gap? How can I fix this?
It seems like the stripe is for status bar. Hide the status bar like follows may resolve your issue.
public RemoveGap()
{
this.InitializeComponent();
if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
{
StatusBar.GetForCurrentView().HideAsync();
}
}
Pay attention, to use this class, we need to add a mobile special reference as following picture shows:

UWP C# ListView not scrollable

I have this ListView:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer VerticalScrollBarVisibility="Visible" VerticalScrollMode="Enabled">
<ListView x:Name="entryList" Width="360">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel BorderBrush="Gray">
<TextBlock Text="{Binding title}"></TextBlock>
<TextBlock Text="{Binding description}"></TextBlock>
<TextBlock Text="{Binding author}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
</Grid>
I get my data for ItemsSource calling a webservice in a seperate method (works all fine)
private async void Page_Loading(Windows.UI.Xaml.FrameworkElement sender, object args)
{
entryList.ItemsSource = await webserviceManager.getItems(param1, param2);
}
My ListView is filled with items as well, but I can't figure out why it isn't able to scroll vertically. Checking the ScrollableHeight I get allways 0 so I think the items are the problem, the control doesn't count them as logical items so far. If I give the ScrollViewer a concrete height all is fine - but thats no viable solution for I don't know on which device the app will run later. So I have no faintest idea what I could do else, maybe somebody can help me?
Edit: the DataSource got a
ObservableCollection<entryObject> objlist = new ObservableCollection<NewsObject>();
where entryObject is a simple data holding class with string properties .
I've solved the Problem - by changing all StackPanels to Grids with RowDefinitions.
<ListView x:Name="entryList" Width="360">
<ListView.ItemTemplate>
<DataTemplate>
<Grid BorderBrush="Gray">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="{Binding title}" Grid.Row="0"></TextBlock>
<TextBlock Text="{Binding description}" Grid.Row="1"></TextBlock>
<TextBlock Text="{Binding author}" Grid.Row="2"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Also I changed my MainPage with the basic SplitView, where the frame in the content panel called the page with the ListView. Here has one of the Grid.Rows a constant height now - and, seems a little bit weird, but all is working fine now.
<SplitView.Content>
<Grid x:Name="mainPagePanel">
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition></RowDefinition>
<Button x:Name="HamburgerButton" FontFamily="Segoe MDL2 Assets" Content="" Width="50" Height="50" Background="Transparent" Click="HamburgerButton_Click" Grid.Row="0"/>
<Frame x:Name="viewFrame" Grid.Row="1"></Frame>
</Grid>
</SplitView.Content>
ListView already contains ScrollViewer in Style. So, just remove your inner ScrollViewer.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView x:Name="entryList" Width="360">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel BorderBrush="Gray">
<TextBlock Text="{Binding title}"></TextBlock>
<TextBlock Text="{Binding description}"></TextBlock>
<TextBlock Text="{Binding author}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>

Hiding/Showing side panel

I am trying to hide/show a panel on the right side of my screen when a button is clicked, however, it is not working exactly as I intended.
Here are a few pics:
Start
This is what my screen originally looks like at startup.
When I click Resize Grid for the first time, this is what the page looks like:
This is actually what I want to happen. The images have shrunk appropriately so that they can all still be viewed.
Two further clicks of Resize Grid results in the 1st image shown above being re-displayed, followed by this:
Can anyone help me with this so that this doesn't occur?
Here is my code so far:
XAML
<Window x:Class="VideoManager.MoviePanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MoviePanel" Height="1024" Width="1463" WindowStartupLocation="CenterScreen">
<Window.Resources>
<DataTemplate x:Key="ItemTemplate">
<WrapPanel Orientation="Vertical" Width="Auto">
<Image Width="200" Height="300" Stretch="Fill" Source="{Binding Image}"/>
<TextBlock Text="{Binding Name}" HorizontalAlignment="Center"/>
</WrapPanel>
</DataTemplate>
</Window.Resources>
<Grid x:Name="movie_grid" HorizontalAlignment="Left" Width="1463">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="102" />
<RowDefinition />
</Grid.RowDefinitions>
<ListView
Name="MovieListView"
ItemTemplate="{StaticResource ItemTemplate}"
ItemsSource="{Binding Path = movies}" Margin="0,0,0,0" SelectionChanged="MovieListView_SelectionChanged" Grid.Row="1">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
<TextBlock x:Name="SampleTextBlock" Margin="1228,36,49,43" >
<InlineUIContainer>
<TextBox Height="23" TextWrapping="Wrap" Text="Search" Width="200" TextChanged="TextBox_TextChanged"/>
</InlineUIContainer>
</TextBlock>
<Button Content="Home" HorizontalAlignment="Left" Margin="46,50,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_Home"/>
<Button Name="collapse" Content="Resize Grid" HorizontalAlignment="Left" Margin="176,50,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
<ListView HorizontalAlignment="Left" Width = "0" Height="872" Grid.Row="1" VerticalAlignment="Top" Name="sidebar" SelectionChanged="sidebar_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn>
<TextBlock Text="hello"/>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
C#
private void Button_Click(object sender, RoutedEventArgs e) {
// collapse main grid and show sidebar
if (this.collapse.Name == "collapse")
{
MovieListView.Margin = new System.Windows.Thickness(0,0,280,0);
sidebar.Width = 280;
sidebar.Margin = new System.Windows.Thickness(1183,0,0,0);
this.collapse.Name = "expand";
}
// expand main grid and hide sidebar
else if (this.collapse.Name == "expand")
{
MovieListView.Width = 1463;
MovieListView.Margin = new System.Windows.Thickness(0, 0, 0, 0);
sidebar.Width = 0;
sidebar.Margin = new System.Windows.Thickness(1463, 0, 0, 0);
this.collapse.Name = "collapse";
}
}
just use the expander control (set it to what direction you desire eg left up right or down) and dont forget to set the window size to auto.
example:
WPF Expander Control

ManipulationCompleted event is not firing on Button

In my Windows Phone 8.1 Universal Application, I have a ListView with a button in the ItemTemplate, and I need to see when that button's ManipulationStarted and ManipulationCompleted events are fired. Currently ManipulationStarted works fine, but ManipulationCompleted does not. Could someone help explain why?
SnapsPage.xaml
<Grid Grid.Row="0" Background="#88686868">
<Grid.RowDefinitions>
<RowDefinition Height="130" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical" Margin="20,0,0,0">
<TextBlock Text="{Binding Path=Manager.Account.Username, FallbackValue='loading...'}" Margin="0,12,0,0" Style="{ThemeResource HeaderTextBlockStyle}"/>
<TextBlock x:Uid="Snaps" Text="SNAPS" Style="{ThemeResource TitleTextBlockStyle}" Typography.Capitals="SmallCaps"/>
</StackPanel>
<ScrollViewer x:Name="ScrollViewer" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled"
Padding="0,0,0,20" Grid.Row="1" HorizontalContentAlignment="Stretch">
<ListView HorizontalContentAlignment="Stretch"
ItemsSource="{Binding Path=Manager.Account.Snaps}">
<ListView.ItemTemplate>
<DataTemplate>
<Button x:Name="ButtonSnap" Style="{StaticResource BasicEmptyButtonStyle}"
ManipulationStarting="ButtonSnap_OnManipulationStarting"
ManipulationCompleted="ButtonSnap_OnManipulationCompleted"
ManipulationMode="All"
Command="{Binding ElementName=ItemsControl, Path=DataContext.TryDownloadMediaCommand}"
CommandParameter="{Binding}">
<!-- Content Here -->
</Button>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel HorizontalAlignment="Stretch"></VirtualizingStackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</ScrollViewer>
</Grid>
<Grid Grid.Row="0" x:Name="MediaGrid" Background="#FF000000" IsHitTestVisible="False">
<Image x:Name="MediaImage" IsHitTestVisible="False"/>
<Grid Width="45" Height="45" Background="#99000000"
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="25">
<TextBlock Text="10" VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Segoe WP Semibold" FontSize="24" />
</Grid>
</Grid>
SnapsPage.cs
private void ButtonSnap_OnManipulationStarting(object sender, ManipulationStartingRoutedEventArgs e)
{
Debug.WriteLine("ButtonSnap_OnManipulationStarting");
var button = sender as Button;
if (button == null) return;
var snap = button.DataContext as Snap;
if (snap == null) return;
_relevantSnap = snap;
_isFingerDown = true;
_scrollYIndex = ScrollViewer.VerticalOffset;
_holdingTimer.Start();
}
private void ButtonSnap_OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
Debug.WriteLine("ButtonSnap_OnManipulationCompleted");
_isFingerDown = false;
if (_isMediaOpen)
DisposeMediaTidily();
}
Note: I tested with Windows Phone 8.1 XAML App (not Silverlight)
The Button has a ManipulationMode of System which, according to the docs, means that you should not get manipulation events.
An element must have a ManipulationMode value other than None or System to be a manipulation event source

Categories