Skip to content

Instantly share code, notes, and snippets.

@Kinnara
Last active October 13, 2015 20:59
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kinnara/9660212 to your computer and use it in GitHub Desktop.
Save Kinnara/9660212 to your computer and use it in GitHub Desktop.
How to disable bounce effect for ScrollViewer when content is not scrollable
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace Kinnara.Phone.Controls
{
public sealed class ScrollContent : ContentPresenter
{
private ScrollViewer _scrollOwner;
private bool _isScrollClient;
private ScrollBarVisibility _originalVerticalScrollBarVisibility;
private Size _contentDesiredSize;
protected override Size MeasureOverride(Size availableSize)
{
InitializeScrollOwner();
if (_scrollOwner != null && !_isScrollClient)
{
_contentDesiredSize = base.MeasureOverride(new Size(availableSize.Width, double.PositiveInfinity));
}
else
{
_contentDesiredSize = base.MeasureOverride(availableSize);
}
UpdateVerticalScrollBarVisibility();
return _contentDesiredSize;
}
private void InitializeScrollOwner()
{
if (_scrollOwner == null)
{
_scrollOwner = GetParentByType<ScrollViewer>(this);
if (_scrollOwner != null)
{
var itemsPresenter = _scrollOwner.Content as ItemsPresenter;
if (itemsPresenter != null)
{
if (VisualTreeHelper.GetChildrenCount(itemsPresenter) > 0)
{
var scrollInfo = VisualTreeHelper.GetChild(itemsPresenter, 0) as IScrollInfo;
if (scrollInfo != null)
{
_isScrollClient = true;
}
}
}
_originalVerticalScrollBarVisibility = _scrollOwner.VerticalScrollBarVisibility;
_scrollOwner.SizeChanged += OnScrollOwnerSizeChanged;
}
}
}
private void OnScrollOwnerSizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateVerticalScrollBarVisibility();
}
private void UpdateVerticalScrollBarVisibility()
{
if (_isScrollClient)
{
if (_scrollOwner.ScrollableHeight > 0)
{
SetVerticalScrollBarVisibility(_originalVerticalScrollBarVisibility);
}
else
{
SetVerticalScrollBarVisibility(ScrollBarVisibility.Disabled);
}
}
else if (_scrollOwner != null && _scrollOwner.ActualHeight > 0)
{
if (_scrollOwner.ViewportHeight < _contentDesiredSize.Height)
{
SetVerticalScrollBarVisibility(_originalVerticalScrollBarVisibility);
}
else
{
SetVerticalScrollBarVisibility(ScrollBarVisibility.Disabled);
}
}
}
private void SetVerticalScrollBarVisibility(ScrollBarVisibility value)
{
if (_scrollOwner.VerticalScrollBarVisibility != value)
{
_scrollOwner.VerticalScrollBarVisibility = value;
}
}
private static T GetParentByType<T>(DependencyObject element)
where T : FrameworkElement
{
Debug.Assert(element != null, "The element cannot be null.");
T result = null;
DependencyObject parent = VisualTreeHelper.GetParent(element);
while (parent != null)
{
result = parent as T;
if (result != null)
{
return result;
}
parent = VisualTreeHelper.GetParent(parent);
}
return null;
}
}
}
<Style x:Key="ScrollViewerVerticalStyle" TargetType="ScrollViewer">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Scrolling">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="NotScrolling">
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="{TemplateBinding Padding}">
<ScrollContentPresenter x:Name="ScrollContentPresenter">
<ScrollContentPresenter.ContentTemplate>
<DataTemplate>
<kpc:ScrollContent Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}" xmlns:kpc="clr-namespace:Kinnara.Phone.Controls"/>
</DataTemplate>
</ScrollContentPresenter.ContentTemplate>
</ScrollContentPresenter>
<ScrollBar x:Name="VerticalScrollBar" IsHitTestVisible="False" Opacity="0" Height="Auto" Width="5" HorizontalAlignment="Right" VerticalAlignment="Stretch" Margin="0,0,1,0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" IsTabStop="False" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Value="{TemplateBinding VerticalOffset}" Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ScrollViewer" BasedOn="{StaticResource ScrollViewerVerticalStyle}"/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment