Sic.Framework-Nanjing-Baishi/MECF.Framework.UI.Client/DataGridTransform/ExtendedGrid/Classes/CustomDataGridRowsPresenter.cs

235 lines
8.9 KiB
C#
Raw Normal View History

2023-04-13 11:51:03 +08:00
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace ExtendedGrid.Classes
{
public class CustomDataGridRowsPresenter : DataGridRowsPresenter
{
/// <summary>
/// Content arrangement.
/// </summary>
/// <param name="arrangeSize">Arrange size</param>
protected override Size ArrangeOverride(Size arrangeSize)
{
if (Owner.FrozenRowCount == 0)
{
return base.ArrangeOverride(arrangeSize);
}
var rcChild = new Rect(arrangeSize);
int frozenRowCount = 0;
double nextFrozenRowStart = 0.0; //indicates the start position for next frozen row
double nextNonFrozenRowStart = 0.0; //indicates the start position for next non-frozen row
double dataGridVerticalScrollStartY = 0.0; //indicates the start position of the vertical scroll bar.
//
// determine the vertical offset, row panel offset and other coordinates used for arrange of children
//
if (Owner != null)
{
double physicalOffset;
var originPoint = new Point(0, 0);
IScrollInfo scrollInfo = this;
{
double verticalOffset = scrollInfo.VerticalOffset;
physicalOffset = -1.0*ComputePhysicalFromLogicalOffset(verticalOffset, false);
rcChild.X = -1.0*scrollInfo.HorizontalOffset;
}
double sbOffset = VerticalScrollBar.TransformToAncestor(ParentPresenter).Transform(originPoint).Y;
double rowsPanelOffset = TransformToAncestor(ParentPresenter).Transform(originPoint).Y; //indicates the offset of rows panel from the start of viewport
nextFrozenRowStart = 0.0;
double viewportStartY = sbOffset - rowsPanelOffset;
//indicates the start of viewport with respect to coordinate system of row panel
nextNonFrozenRowStart -= physicalOffset - viewportStartY;
if (Owner.FrozenRowCount != null) frozenRowCount = (int) Owner.FrozenRowCount;
//Debug.WriteLine(string.Format(
// "verticalOffset: {0}, physicalOffset: {1}, sbOffset: {2}, viewportStartY: {3}, nextNonFrozeRowStart: {4}",
// verticalOffset,
// physicalOffset,
// sbOffset,
// viewportStartY,
// nextNonFrozenRowStart));
}
//
// Arrange and Position Children.
//
var children = GetRealizedChildren;
for (int i = 0; i < children.Count; ++i)
{
// we are looping through the actual containers; the visual children of this panel.
var container = (UIElement) children[i];
var childSize = container.DesiredSize;
//TODO: need to handle virtualization
// container = ParentPresenter.ItemContainerGenerator.ContainerFromIndex(i) as UIElement;
// if (container != null)
// {
// childSize = container.DesiredSize;
// }
// else
// {
// //TODO: handle sizing for virtualization
// }
//}
rcChild.Height = childSize.Height;
rcChild.Width = Math.Max(arrangeSize.Width, childSize.Width);
if (i < frozenRowCount)
{
rcChild.Y = nextFrozenRowStart;
nextFrozenRowStart += childSize.Height;
dataGridVerticalScrollStartY += childSize.Height;
}
else
{
if (DoubleUtil.LessThan(nextNonFrozenRowStart, nextFrozenRowStart))
{
IScrollInfo scrollInfo = this;
var verticalOffset = scrollInfo.VerticalOffset;
if (DoubleUtil.LessThan(nextNonFrozenRowStart + childSize.Height, nextFrozenRowStart))
{
nextNonFrozenRowStart += childSize.Height;
}
else
{
double rowChoppedHeight = nextFrozenRowStart - nextNonFrozenRowStart;
if (DoubleUtil.AreClose(rowChoppedHeight, 0.0))
{
nextNonFrozenRowStart = nextFrozenRowStart + childSize.Height;
}
else
{
double clipHeight = childSize.Height - rowChoppedHeight;
nextNonFrozenRowStart = nextFrozenRowStart + clipHeight;
}
}
rcChild.Y = nextFrozenRowStart;
}
else
{
rcChild.Y = nextNonFrozenRowStart;
nextNonFrozenRowStart += childSize.Height;
}
}
container.Arrange(rcChild);
}
if (Owner != null)
{
Owner.NonFrozenRowsViewportVerticalOffset = dataGridVerticalScrollStartY;
}
return arrangeSize;
}
/// <summary>
/// override of ViewportOffsetChanged method which forwards the call to datagrid on vertical scroll
/// </summary>
/// <param name="oldViewportOffset"></param>
/// <param name="newViewportOffset"></param>
protected override void OnViewportOffsetChanged(Vector oldViewportOffset, Vector newViewportOffset)
{
base.OnViewportOffsetChanged(oldViewportOffset, newViewportOffset);
if (!DoubleUtil.AreClose(oldViewportOffset.Y, newViewportOffset.Y))
{
Base.CustomDg dataGrid = Owner;
if (dataGrid != null)
{
dataGrid.OnVerticalScroll();
}
}
}
#region Helpers
private double ComputePhysicalFromLogicalOffset(double logicalOffset, bool fHorizontal)
{
double physicalOffset = 0.0;
IList children = GetRealizedChildren;
const double epsilon = 0;
if(Math.Abs(logicalOffset - 0) < epsilon|| (logicalOffset > 0 && logicalOffset < children.Count))
{
// Debug.Assert(Math.Abs(logicalOffset - 0) < epsilon || (logicalOffset > 0 && logicalOffset < children.Count));
}
for (int i = 0; i < logicalOffset; i++)
{
var child = (UIElement) children[i];
physicalOffset -= (fHorizontal)
? child.DesiredSize.Width
: child.DesiredSize.Height;
}
return physicalOffset;
}
private ItemsControl ParentPresenter
{
get
{
var itemsPresenter = TemplatedParent as FrameworkElement;
if (itemsPresenter != null)
{
return itemsPresenter.TemplatedParent as ItemsControl;
}
return null;
}
}
private IList GetRealizedChildren
{
get
{
return (IList) typeof (VirtualizingStackPanel).InvokeMember("RealizedChildren",
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.GetProperty,
null, this, null);
}
}
private ScrollBar VerticalScrollBar
{
get
{
if (_verticalScrollBar == null)
{
_verticalScrollBar = (ScrollBar) Helper.FindPartByName(ParentPresenter, "PART_VerticalScrollBar");
_verticalScrollBar.UpdateLayout();
}
return _verticalScrollBar;
}
}
private Base.CustomDg Owner
{
get { return _owner ?? (_owner = ItemsControl.GetItemsOwner(this) as Base.CustomDg); }
}
#endregion Helpers
#region Data
private Base.CustomDg _owner;
private ScrollBar _verticalScrollBar;
#endregion Data
}
}