Je vyžadována podpora jazyka JavaScript
Některé stránky na tomto webu vyžadují podporu jazyka JavaScript. Váš webový prohlížeč jazyk JavaScript nepodporuje nebo jazyk JavaScript není povolen.
Chcete-li zjistit, zda webový prohlížeč podporuje jazyk JavaScript nebo jazyk JavaScript chcete povolit, přečtěte si nápovědu k vašemu webovému prohlížeči.
ScrollableWrapPanel.cs
Download fileToto je zdrojový kód souboru ScrollableWrapPanel.cs
WrapPanel Silverlight Control with IScrollInfo support.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.ComponentModel;
namespace IMP.Windows.Controls
{
/// <summary>
/// WrapPanel with IScrollInfo support
/// </summary>
/// <remarks>
/// Add <c>VerticalScrollChange</c> and <c>HorizontalScrollChange</c> properties
/// </remarks>
public partial class ScrollableWrapPanel : WrapPanel, System.Windows.Controls.Primitives.IScrollInfo
{
#region constants
private const double cDefaultVerticalScrollChange = 22.0;
private const double cDefaultHorizontalScrollChange = 66.0;
#endregion
#region member varible and default property initialization
private bool m_CanHorizontallyScroll;
private bool m_CanVerticallyScroll;
private ScrollViewer m_ScrollOwner;
private Vector m_Offset;
private Size m_Extent;
private Size m_Viewport;
#endregion
#region action methods
/// <summary>
/// Scrolls up within the content by one logical unit.
/// </summary>
public virtual void LineUp()
{
this.SetVerticalOffset(this.VerticalOffset - this.VerticalScrollChange);
}
/// <summary>
/// Scrolls down within the content by one logical unit.
/// </summary>
public virtual void LineDown()
{
this.SetVerticalOffset(this.VerticalOffset + this.VerticalScrollChange);
}
/// <summary>
/// Scrolls left within the content by one logical unit.
/// </summary>
public virtual void LineLeft()
{
this.SetHorizontalOffset(this.HorizontalOffset - this.HorizontalScrollChange);
}
/// <summary>
/// Scrolls right within the content by one logical unit.
/// </summary>
public virtual void LineRight()
{
this.SetHorizontalOffset(this.HorizontalOffset + this.HorizontalScrollChange);
}
/// <summary>
/// Scrolls up within the content after the user clicks the wheel button on a mouse.
/// </summary>
public virtual void MouseWheelUp()
{
this.SetVerticalOffset(this.VerticalOffset - (SystemParameters.WheelScrollLines * this.VerticalScrollChange));
}
/// <summary>
/// Scrolls down within the content after the user clicks the wheel button on a mouse.
/// </summary>
public virtual void MouseWheelDown()
{
this.SetVerticalOffset(this.VerticalOffset + (SystemParameters.WheelScrollLines * this.VerticalScrollChange));
}
/// <summary>
/// Scrolls left within the content after the user clicks the wheel button on a mouse.
/// </summary>
public virtual void MouseWheelLeft()
{
this.SetHorizontalOffset(this.HorizontalOffset - (3.0 * this.HorizontalScrollChange));
}
/// <summary>
/// Scrolls right within the content after the user clicks the wheel button on a mouse.
/// </summary>
public virtual void MouseWheelRight()
{
this.SetHorizontalOffset(this.HorizontalOffset + (3.0 * this.HorizontalScrollChange));
}
/// <summary>
/// Scrolls up within the content by one page.
/// </summary>
public virtual void PageUp()
{
this.SetVerticalOffset(this.VerticalOffset - this.ViewportHeight);
}
/// <summary>
/// Scrolls down within the content by one page.
/// </summary>
public virtual void PageDown()
{
this.SetVerticalOffset(this.VerticalOffset + this.ViewportHeight);
}
/// <summary>
/// Scrolls left within the content by one page.
/// </summary>
public virtual void PageLeft()
{
this.SetHorizontalOffset(this.HorizontalOffset - this.ViewportWidth);
}
/// <summary>
/// Scrolls right within the content by one page.
/// </summary>
public virtual void PageRight()
{
this.SetHorizontalOffset(this.HorizontalOffset + this.ViewportWidth);
}
/// <summary>
/// Sets the amount of horizontal offset.
/// </summary>
/// <param name="offset">The amount that content is horizontally offset from the containing viewport.</param>
public void SetHorizontalOffset(double offset)
{
if (this.CanHorizontallyScroll)
{
double X = Math.Max(0.0, Math.Min(offset, this.ExtentWidth - this.ViewportWidth));
if (X != m_Offset.X)
{
m_Offset.X = X;
this.InvalidateArrange();
}
}
}
/// <summary>
/// Sets the amount of vertical offset.
/// </summary>
/// <param name="offset">The amount that content is vertically offset from the containing viewport.</param>
public void SetVerticalOffset(double offset)
{
if (this.CanVerticallyScroll)
{
double Y = Math.Max(0.0, Math.Min(offset, this.ExtentHeight - this.ViewportHeight));
if (Y != m_Offset.Y)
{
m_Offset.Y = Y;
base.InvalidateArrange();
}
}
}
/// <summary>
/// Forces content to scroll until the coordinate space of a visual object is visible.
/// </summary>
/// <param name="visual">A System.Windows.UIElement that becomes visible.</param>
/// <param name="rectangle">A bounding rectangle that identifies the coordinate space to make visible.</param>
/// <returns>A System.Windows.Rect that is visible.</returns>
public Rect MakeVisible(UIElement visual, Rect rectangle)
{
if (rectangle.IsEmpty || visual == null || visual == this || !IsAncestorOf(visual))
{
return Rect.Empty;
}
Point point = visual.TransformToVisual(this).Transform(new Point(rectangle.X, rectangle.Y));
rectangle.X = point.X;
rectangle.Y = point.Y;
Rect viewRect = new Rect(this.HorizontalOffset, this.VerticalOffset, this.ViewportWidth, this.ViewportHeight);
rectangle.X += viewRect.X;
rectangle.Y += viewRect.Y;
double X = ComputeScrollOffset(viewRect.Left, viewRect.Right, rectangle.Left, rectangle.Right);
double Y = ComputeScrollOffset(viewRect.Top, viewRect.Bottom, rectangle.Top, rectangle.Bottom);
this.SetHorizontalOffset(X);
this.SetVerticalOffset(Y);
viewRect.X = X;
viewRect.Y = Y;
rectangle.Intersect(viewRect);
if (!rectangle.IsEmpty)
{
rectangle.X -= viewRect.X;
rectangle.Y -= viewRect.Y;
}
return rectangle;
}
#endregion
#region property getters/setters
/// <summary>
/// VerticalScrollChange dependency property
/// </summary>
public static readonly DependencyProperty VerticalScrollChangeProperty = DependencyProperty.Register("VerticalScrollChange", typeof(double), typeof(ScrollableWrapPanel), new PropertyMetadata(cDefaultVerticalScrollChange));
/// <summary>
/// Vertical Scroll Change
/// </summary>
[DefaultValue(cDefaultVerticalScrollChange)]
public double VerticalScrollChange
{
get { return (double)base.GetValue(VerticalScrollChangeProperty); }
set { base.SetValue(VerticalScrollChangeProperty, value); }
}
/// <summary>
/// HorizontalScrollChange dependency property
/// </summary>
public static readonly DependencyProperty HorizontalScrollChangeProperty = DependencyProperty.Register("HorizontalScrollChange", typeof(double), typeof(ScrollableWrapPanel), new PropertyMetadata(cDefaultHorizontalScrollChange));
/// <summary>
/// Horizontal Scroll Change
/// </summary>
[DefaultValue(cDefaultHorizontalScrollChange)]
public double HorizontalScrollChange
{
get { return (double)base.GetValue(HorizontalScrollChangeProperty); }
set { base.SetValue(HorizontalScrollChangeProperty, value); }
}
/// <summary>
/// Gets the horizontal offset of the scrolled content.
/// </summary>
public double HorizontalOffset
{
get { return m_Offset.X; }
}
/// <summary>
/// Gets the vertical offset of the scrolled content.
/// </summary>
public double VerticalOffset
{
get { return m_Offset.Y; }
}
/// <summary>
/// Gets the vertical size of the extent.
/// </summary>
public double ExtentHeight
{
get { return m_Extent.Height; }
}
/// <summary>
/// Gets the horizontal size of the extent.
/// </summary>
public double ExtentWidth
{
get { return m_Extent.Width; }
}
/// <summary>
/// Gets the vertical size of the viewport for this content.
/// </summary>
public double ViewportHeight
{
get { return m_Viewport.Height; }
}
/// <summary>
/// Gets the horizontal size of the viewport for this content.
/// </summary>
public double ViewportWidth
{
get { return m_Viewport.Width; }
}
/// <summary>
/// Gets or sets a value that indicates whether scrolling on the horizontal axis is possible.
/// </summary>
public bool CanHorizontallyScroll
{
get { return m_CanHorizontallyScroll; }
set { m_CanHorizontallyScroll = value; }
}
/// <summary>
/// Gets or sets a value that indicates whether scrolling on the vertical axis is possible.
/// </summary>
public bool CanVerticallyScroll
{
get { return m_CanVerticallyScroll; }
set { m_CanVerticallyScroll = value; }
}
/// <summary>
/// Gets or sets a System.Windows.Controls.ScrollViewer element that controls scrolling behavior.
/// </summary>
public ScrollViewer ScrollOwner
{
get { return m_ScrollOwner; }
set { m_ScrollOwner = value; }
}
#endregion
#region override methods
/// <summary>
/// Overrides MeasureOverride
/// </summary>
protected override Size MeasureOverride(Size constraint)
{
var desiredSize = base.MeasureOverride(constraint);
this.VerifyScrollData(constraint, desiredSize);
return desiredSize;
}
/// <summary>
/// Overrides ArrangeOverride
/// </summary>
protected override Size ArrangeOverride(Size arrangeSize)
{
var size = base.ArrangeOverride(arrangeSize);
for (int i = 0; i < Children.Count; i++)
{
UIElement element = Children[i];
Size desiredSize = element.DesiredSize;
var gt = element.TransformToVisual(this);
var pos = gt.Transform(new Point(0, 0));
var finalRect = new Rect(pos.X - m_Offset.X, pos.Y - m_Offset.Y, desiredSize.Width, desiredSize.Height);
element.Arrange(finalRect);
}
return size;
}
#endregion
#region private member functions
private void VerifyScrollData(Size viewport, Size extent)
{
m_Viewport = viewport;
m_Extent = extent;
if (m_Offset.X > (m_Extent.Width - m_Viewport.Width))
{
m_Offset.X = m_Extent.Width - m_Viewport.Width;
}
if (m_Offset.X < 0.0)
{
m_Offset.X = 0.0;
}
if (m_Offset.Y > (m_Extent.Height - m_Viewport.Height))
{
m_Offset.Y = m_Extent.Height - m_Viewport.Height;
}
if (m_Offset.Y < 0.0)
{
m_Offset.Y = 0.0;
}
if (this.ScrollOwner != null)
{
this.ScrollOwner.InvalidateScrollInfo();
}
}
private bool IsAncestorOf(UIElement element)
{
UIElement panel = this;
UIElement reference = element;
while (reference != null && reference != panel)
{
reference = VisualTreeHelper.GetParent(reference) as UIElement;
}
return reference == panel;
}
private static double ComputeScrollOffset(double topView, double bottomView, double topChild, double bottomChild)
{
bool offBottom = topChild < topView && bottomChild < bottomView;
bool offTop = bottomChild > bottomView && topChild > topView;
bool tooLarge = (bottomChild - topChild) > (bottomView - topView);
if (!offBottom && !offTop)
{
//Don't do anything, already in view
return topView;
}
if ((offBottom && !tooLarge) || (offTop && tooLarge))
{
return topChild;
}
return (bottomChild - (bottomView - topView));
}
#endregion
}
}