Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4589 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
12 changed files with 603 additions and 93 deletions
@ -0,0 +1,176 @@
@@ -0,0 +1,176 @@
|
||||
<UserControl x:Class="ICSharpCode.SharpDevelop.Debugging.DebuggerTooltipControl" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
<UserControl.Resources> |
||||
<!-- TODO move styles to ResourceDictionary --> |
||||
<Style x:Key="ExpandCollapseToggleStyle" |
||||
TargetType="{x:Type ToggleButton}"> |
||||
<Setter Property="Focusable" |
||||
Value="False"/> |
||||
<Setter Property="Width" |
||||
Value="19"/> |
||||
<Setter Property="Height" |
||||
Value="13"/> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="{x:Type ToggleButton}"> |
||||
<Border Width="19" |
||||
Height="13" |
||||
Background="Transparent"> |
||||
<Border Width="9" |
||||
Height="9" |
||||
BorderThickness="1" |
||||
BorderBrush="#FF7898B5" |
||||
CornerRadius="1" |
||||
SnapsToDevicePixels="true"> |
||||
<Border.Background> |
||||
<LinearGradientBrush StartPoint="0,0" |
||||
EndPoint="1,1"> |
||||
<LinearGradientBrush.GradientStops> |
||||
<GradientStop Color="White" |
||||
Offset=".2"/> |
||||
<GradientStop Color="#FFC0B7A6" |
||||
Offset="1"/> |
||||
</LinearGradientBrush.GradientStops> |
||||
</LinearGradientBrush> |
||||
</Border.Background> |
||||
<Path x:Name="ExpandPath" |
||||
Margin="1,1,1,1" |
||||
Fill="Black" |
||||
Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z"/> |
||||
</Border> |
||||
</Border> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger Property="IsChecked" |
||||
Value="True"> |
||||
<Setter Property="Data" |
||||
TargetName="ExpandPath" |
||||
Value="M 0 2 L 0 3 L 5 3 L 5 2 Z"/> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
<Style x:Key="upDownBorderStyle" TargetType="{x:Type Border}"> |
||||
<Setter Property="BorderBrush" Value="Gray" /> |
||||
<Setter Property="HorizontalAlignment" Value="Stretch" /> |
||||
<Setter Property="Margin" Value="0" /> |
||||
<Setter Property="Background" Value="#FFECF7FC" /> |
||||
<Style.Triggers> |
||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="False"> |
||||
<Setter Property="Background" Value="#FFE0E0E0"></Setter> |
||||
</DataTrigger> |
||||
</Style.Triggers> |
||||
</Style> |
||||
<Style x:Key="upButtonStyle" TargetType="{x:Type RepeatButton}"> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="{x:Type RepeatButton}"> |
||||
<Border Style="{StaticResource upDownBorderStyle}" BorderThickness="1 1 1 0"> |
||||
<ContentPresenter HorizontalAlignment="Center"></ContentPresenter> |
||||
</Border> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
<Style x:Key="downButtonStyle" TargetType="{x:Type RepeatButton}"> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="{x:Type RepeatButton}"> |
||||
<Border Style="{StaticResource upDownBorderStyle}" BorderThickness="1 0 1 1"> |
||||
<ContentPresenter HorizontalAlignment="Center"></ContentPresenter> |
||||
</Border> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
</UserControl.Resources> |
||||
<StackPanel Orientation="Vertical"> |
||||
<RepeatButton Name="btnUp" Style="{StaticResource upButtonStyle}" Content="^" Click="BtnUp_Click"></RepeatButton> |
||||
<DataGrid VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled" |
||||
GridLinesVisibility="None" |
||||
RowHeight="20" MaxHeight="202" |
||||
SelectionMode="Single" |
||||
SelectionUnit="FullRow" |
||||
ItemsSource="{Binding}" |
||||
Name="dataGrid" |
||||
AutoGenerateColumns="False" |
||||
CanUserAddRows="False" HeadersVisibility="None" |
||||
BorderBrush="Gray" |
||||
BorderThickness="1"> |
||||
<DataGrid.Background> |
||||
<LinearGradientBrush StartPoint="0,-0.03" EndPoint="0,1"> |
||||
<GradientStop Color="White"/> |
||||
<GradientStop Color="#FFFAFCFE" Offset="0.983"/> |
||||
<GradientStop Color="#FFECF7FC" Offset="0.07"/> |
||||
<GradientStop Color="#FFEEF7FA" Offset="0.436"/> |
||||
</LinearGradientBrush> |
||||
</DataGrid.Background> |
||||
<DataGrid.RowStyle> |
||||
<Style TargetType="{x:Type DataGridRow}"> |
||||
<Setter Property="Background" Value="Transparent"></Setter> |
||||
<Style.Triggers> |
||||
<Trigger Property="IsMouseOver" Value="True"> |
||||
<Setter Property="Background" Value="#FFE2F6FE" /> |
||||
</Trigger> |
||||
</Style.Triggers> |
||||
</Style> |
||||
</DataGrid.RowStyle> |
||||
<DataGrid.CellStyle> |
||||
<Style TargetType="{x:Type DataGridCell}"> |
||||
<Setter Property="Focusable" Value="false" /> |
||||
<Setter Property="BorderThickness" Value="0" /> |
||||
</Style> |
||||
</DataGrid.CellStyle> |
||||
<DataGrid.Columns> |
||||
<DataGridTemplateColumn> <!-- "Plus" expander --> |
||||
<DataGridTemplateColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<Grid Background="White"> |
||||
<StackPanel VerticalAlignment="Center"> |
||||
<ToggleButton x:Name="PropertyExpander" Style="{StaticResource ExpandCollapseToggleStyle}" Click="Expander_Click" Padding="0" Margin="0 0 0 0" /> |
||||
</StackPanel> |
||||
</Grid> |
||||
<DataTemplate.Triggers> |
||||
<DataTrigger Binding="{Binding Path=ShowPropertyButton}" Value="False"> |
||||
<Setter TargetName="PropertyExpander" |
||||
Property="Visibility" Value="Hidden"/> |
||||
</DataTrigger> |
||||
</DataTemplate.Triggers> |
||||
</DataTemplate> |
||||
</DataGridTemplateColumn.CellTemplate> |
||||
</DataGridTemplateColumn> |
||||
<!-- Icon |
||||
<DataGridTemplateColumn> |
||||
<DataGridTemplateColumn.CellTemplate> |
||||
<DataTemplate> |
||||
</DataTemplate> |
||||
</DataGridTemplateColumn.CellTemplate> |
||||
</DataGridTemplateColumn> --> |
||||
<DataGridTemplateColumn MinWidth="20" Header="Name"> <!-- Name --> |
||||
<DataGridTemplateColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<Border BorderBrush="#FFDDDDDD" BorderThickness="0 0 1 0"> |
||||
<TextBlock Margin="0 0 6 0" Text="{Binding Path=Name, Mode=OneWay}"></TextBlock> |
||||
</Border> |
||||
</DataTemplate> |
||||
</DataGridTemplateColumn.CellTemplate> |
||||
</DataGridTemplateColumn> |
||||
<!-- Visualizer picker |
||||
<DataGridTemplateColumn> |
||||
<DataGridTemplateColumn.CellTemplate> |
||||
<DataTemplate> |
||||
</DataTemplate> |
||||
</DataGridTemplateColumn.CellTemplate> |
||||
</DataGridTemplateColumn> --> |
||||
<!-- Value --> |
||||
<DataGridTextColumn MinWidth="20" |
||||
Header="Value" Width="Auto" |
||||
Binding="{Binding Path=Value, Mode=OneWay}"/> |
||||
</DataGrid.Columns> |
||||
</DataGrid> |
||||
<RepeatButton Name="btnDown" Style="{StaticResource downButtonStyle}" Content="v" Click="BtnDown_Click"></RepeatButton> |
||||
</StackPanel> |
||||
</UserControl> |
||||
@ -0,0 +1,103 @@
@@ -0,0 +1,103 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Martin Koníček" email="martin.konicek@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Text; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Controls.Primitives; |
||||
using System.Windows.Data; |
||||
using System.Windows.Documents; |
||||
using System.Windows.Input; |
||||
using System.Windows.Media; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Debugging |
||||
{ |
||||
/// <summary>
|
||||
/// Default Control used as content of SharpDevelop debugger tooltips.
|
||||
/// </summary>
|
||||
public partial class DebuggerTooltipControl : UserControl, ITooltip |
||||
{ |
||||
public DebuggerTooltipControl() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
|
||||
private LazyItemsControl<ITreeNode> lazyGrid; |
||||
|
||||
private IEnumerable<ITreeNode> itemsSource; |
||||
public IEnumerable<ITreeNode> ItemsSource |
||||
{ |
||||
set |
||||
{ |
||||
this.itemsSource = value; |
||||
this.lazyGrid = new LazyItemsControl<ITreeNode>(this.dataGrid, 12); |
||||
lazyGrid.ItemsSource = new VirtualizingIEnumerable<ITreeNode>(value); |
||||
this.dataGrid.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(handleScroll)); |
||||
|
||||
if (this.lazyGrid.ItemsSourceTotalCount != null) |
||||
{ |
||||
btnUp.Visibility = btnDown.Visibility = |
||||
this.lazyGrid.ItemsSourceTotalCount.Value <= 10 ? Visibility.Collapsed : Visibility.Visible; |
||||
} |
||||
} |
||||
get |
||||
{ |
||||
return this.itemsSource; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Determines whether DebuggerTooltipControl should be displayed in WPF Popup.
|
||||
/// </summary>
|
||||
public bool ShowAsPopup { |
||||
get { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Closes the debugger Popup containing this control. Also closes all child Popups.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Close() |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
private void Expander_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
var clickedButton = (ToggleButton)e.OriginalSource; |
||||
Point buttonPos = clickedButton.PointToScreen(new Point(0, 0)); |
||||
|
||||
if (clickedButton.IsChecked.GetValueOrDefault(false)) |
||||
{ |
||||
// open child Popup
|
||||
} |
||||
else |
||||
{ |
||||
// close child Popups
|
||||
} |
||||
} |
||||
|
||||
private void handleScroll(object sender, ScrollChangedEventArgs e) |
||||
{ |
||||
btnUp.IsEnabled = !this.lazyGrid.IsScrolledToStart; |
||||
btnDown.IsEnabled = !this.lazyGrid.IsScrolledToEnd; |
||||
} |
||||
|
||||
void BtnUp_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
this.lazyGrid.ScrollViewer.ScrollUp(1); |
||||
} |
||||
|
||||
void BtnDown_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
this.lazyGrid.ScrollViewer.ScrollDown(1); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Martin Koníček" email="martin.konicek@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Debugging |
||||
{ |
||||
/// <summary>
|
||||
/// Content of debugger tooltip, specifying whether it should be displayed in a WPF Popup.
|
||||
/// </summary>
|
||||
public interface ITooltip |
||||
{ |
||||
/// <summary>
|
||||
/// If true, this ITooltip will be displayed in a WPF Popup.
|
||||
/// Otherwise this will be displayed in a WPF Tooltip.
|
||||
/// WPF Popups are (unlike WPF Tooltips) focusable.
|
||||
/// </summary>
|
||||
bool ShowAsPopup { get; } |
||||
|
||||
/// <summary>
|
||||
/// Closes this debugger tooltip.
|
||||
/// </summary>
|
||||
/// <returns>True if Close succeeded, false otherwise.</returns>
|
||||
bool Close(); |
||||
} |
||||
} |
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Martin Koníček" email="martin.konicek@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Debugging |
||||
{ |
||||
/// <summary>
|
||||
/// Node that can be bound to DebuggerTooltipControl.
|
||||
/// </summary>
|
||||
public interface ITreeNode |
||||
{ |
||||
string Name { get; } |
||||
|
||||
string Text { get; } |
||||
|
||||
string Type { get; } |
||||
|
||||
IEnumerable<ITreeNode> ChildNodes { get; } |
||||
} |
||||
} |
||||
@ -0,0 +1,120 @@
@@ -0,0 +1,120 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Martin Koníček" email="martin.konicek@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Windows.Controls; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Debugging |
||||
{ |
||||
/// <summary>
|
||||
/// ItemsControl wrapper that takes VirtualizingIEnumerable as source,
|
||||
/// and adds additional items from the source to underlying ItemsControl when scrolled to bottom.
|
||||
/// </summary>
|
||||
public class LazyItemsControl<T> |
||||
{ |
||||
private ItemsControl itemsControl; |
||||
private int initialItemsCount; |
||||
|
||||
/// <summary>
|
||||
/// Creates new instance of LazyItemsControl.
|
||||
/// </summary>
|
||||
/// <param name="wrappedItemsControl">ItemsControl to wrap and add items to it when scrolled to bottom.</param>
|
||||
/// <param name="initialItemsCount">Number of items to be initially displayed in wrapped ItemsControl.</param>
|
||||
public LazyItemsControl(ItemsControl wrappedItemsControl, int initialItemsCount) |
||||
{ |
||||
if (wrappedItemsControl == null) |
||||
throw new ArgumentNullException("wrappedItemsControl"); |
||||
|
||||
this.initialItemsCount = initialItemsCount; |
||||
this.itemsControl = wrappedItemsControl; |
||||
this.itemsControl.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(handleScroll)); |
||||
} |
||||
|
||||
private ScrollViewer scrollViewerCached; |
||||
public ScrollViewer ScrollViewer |
||||
{ |
||||
get |
||||
{ |
||||
if (this.scrollViewerCached == null) |
||||
this.scrollViewerCached = this.itemsControl.GetScrollViewer(); |
||||
return this.scrollViewerCached; |
||||
} |
||||
} |
||||
|
||||
public bool IsScrolledToStart |
||||
{ |
||||
get |
||||
{ |
||||
if (ScrollViewer == null) // Visual tree not initialized yet
|
||||
return false; |
||||
return ScrollViewer.VerticalOffset == 0; |
||||
} |
||||
} |
||||
|
||||
public bool IsScrolledToEnd |
||||
{ |
||||
get |
||||
{ |
||||
if (itemsSourceTotalCount == null) { |
||||
// not scrolled to end of IEnumerable yet
|
||||
return false; |
||||
} |
||||
// already scrolled to end of IEnumerable
|
||||
int totalItems = itemsSourceTotalCount.Value; |
||||
return (ScrollViewer.VerticalOffset >= totalItems - ScrollViewer.ViewportHeight); |
||||
} |
||||
} |
||||
|
||||
private int? itemsSourceTotalCount = null; |
||||
/// <summary> Items count of underlying IEnumerable. Null until scrolled to the end of IEnumerable. </summary>
|
||||
public int? ItemsSourceTotalCount |
||||
{ |
||||
get |
||||
{ |
||||
return this.itemsSourceTotalCount; |
||||
} |
||||
} |
||||
|
||||
private VirtualizingIEnumerable<T> itemsSource; |
||||
/// <summary> The collection that underlying ItemsControl sees. </summary>
|
||||
public VirtualizingIEnumerable<T> ItemsSource |
||||
{ |
||||
get |
||||
{ |
||||
return itemsSource; |
||||
} |
||||
set |
||||
{ |
||||
this.itemsSource = value; |
||||
addNextItems(this.itemsSource, initialItemsCount); |
||||
this.itemsControl.ItemsSource = value; |
||||
} |
||||
} |
||||
|
||||
private void addNextItems(VirtualizingIEnumerable<T> sourceToAdd, int nItems) |
||||
{ |
||||
sourceToAdd.AddNextItems(nItems); |
||||
if (!sourceToAdd.HasNext) |
||||
{ |
||||
// all items from IEnumerable have been added
|
||||
this.itemsSourceTotalCount = sourceToAdd.Count; |
||||
} |
||||
} |
||||
|
||||
private void handleScroll(object sender, ScrollChangedEventArgs e) |
||||
{ |
||||
if (e.VerticalChange > 0) |
||||
{ |
||||
// scrolled to bottom
|
||||
if (e.VerticalOffset >= this.itemsSource.Count - e.ViewportHeight) |
||||
{ |
||||
addNextItems(this.itemsSource, (int)e.VerticalChange); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Martin Koníček" email="martin.konicek@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Debugging |
||||
{ |
||||
/// <summary>
|
||||
/// A wrapper around IEnumerable<T> with AddNextItems method for pulling additional items
|
||||
/// from underlying IEnumerable<T>.
|
||||
/// Can be used as source for <see cref="LazyItemsControl" />.
|
||||
/// </summary>
|
||||
public class VirtualizingIEnumerable<T> : ObservableCollection<T> |
||||
{ |
||||
private IEnumerator<T> originalSourceEnumerator; |
||||
|
||||
public VirtualizingIEnumerable(IEnumerable<T> originalSource) |
||||
{ |
||||
if (originalSource == null) |
||||
throw new ArgumentNullException("originalSource"); |
||||
|
||||
this.originalSourceEnumerator = originalSource.GetEnumerator(); |
||||
} |
||||
|
||||
private bool hasNext = true; |
||||
/// <summary>
|
||||
/// False if all items from underlying IEnumerable have already been added.
|
||||
/// </summary>
|
||||
public bool HasNext |
||||
{ |
||||
get |
||||
{ |
||||
return this.hasNext; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Requests next <paramref name="count"/> items from underlying IEnumerable source and adds them to the collection.
|
||||
/// </summary>
|
||||
public void AddNextItems(int count) |
||||
{ |
||||
for (int i = 0; i < count; i++) |
||||
{ |
||||
if (!originalSourceEnumerator.MoveNext()) |
||||
{ |
||||
this.hasNext = false; |
||||
break; |
||||
} |
||||
this.Add(originalSourceEnumerator.Current); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Martin Koníèek" email="martin.konicek@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Media; |
||||
|
||||
namespace ICSharpCode.SharpDevelop |
||||
{ |
||||
/// <summary>
|
||||
/// Scrolling related helpers.
|
||||
/// </summary>
|
||||
public static class ScrollUtils |
||||
{ |
||||
/// <summary>
|
||||
/// Searches VisualTree of given object for a ScrollViewer.
|
||||
/// </summary>
|
||||
public static ScrollViewer GetScrollViewer(this DependencyObject o) |
||||
{ |
||||
var scrollViewer = o as ScrollViewer; |
||||
if (scrollViewer != null) { |
||||
return scrollViewer; |
||||
} |
||||
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++) |
||||
{ |
||||
var child = VisualTreeHelper.GetChild(o, i); |
||||
var result = GetScrollViewer(child); |
||||
if (result != null) { |
||||
return result; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Scrolls ScrollViewer up by given offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset by which to scroll up. Should be positive.</param>
|
||||
public static void ScrollUp(this ScrollViewer scrollViewer, double offset) |
||||
{ |
||||
ScrollUtils.ScrollByVerticalOffset(scrollViewer, -offset); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Scrolls ScrollViewer down by given offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset by which to scroll down. Should be positive.</param>
|
||||
public static void ScrollDown(this ScrollViewer scrollViewer, double offset) |
||||
{ |
||||
ScrollUtils.ScrollByVerticalOffset(scrollViewer, offset); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Scrolls ScrollViewer by given vertical offset.
|
||||
/// </summary>
|
||||
public static void ScrollByVerticalOffset(this ScrollViewer scrollViewer, double offset) |
||||
{ |
||||
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue