using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Markup; using System.Windows.Shapes; using System.Windows.Threading; using Tango.Core.Threading; namespace Tango.Touch.Controls { [ContentProperty(nameof(Content))] public class TouchVirtualizedContentReplaceControl : Control { private LightTouchScrollViewer _scrollViewer; private Border _innerBorder; private ActionTimer _updateTimer; private Point _location; private bool _loaded; private Image _replaceContent; private FrameworkElement _element; private INameScopeDictionary _parentNameScope; public DataTemplate Content { get { return (DataTemplate)GetValue(ContentProperty); } set { SetValue(ContentProperty, value); } } public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(DataTemplate), typeof(TouchVirtualizedContentReplaceControl), new PropertyMetadata(null)); public bool CanMovePosition { get { return (bool)GetValue(CanMovePositionProperty); } set { SetValue(CanMovePositionProperty, value); } } public static readonly DependencyProperty CanMovePositionProperty = DependencyProperty.Register("CanMovePosition", typeof(bool), typeof(TouchVirtualizedContentReplaceControl), new PropertyMetadata(false)); public LightTouchDataGrid DataGrid { get { return (LightTouchDataGrid)GetValue(DataGridProperty); } set { SetValue(DataGridProperty, value); } } public static readonly DependencyProperty DataGridProperty = DependencyProperty.Register("DataGrid", typeof(LightTouchDataGrid), typeof(TouchVirtualizedContentReplaceControl), new PropertyMetadata(null)); public bool Disconnect { get { return (bool)GetValue(DisconnectProperty); } set { SetValue(DisconnectProperty, value); } } public static readonly DependencyProperty DisconnectProperty = DependencyProperty.Register("Disconnect", typeof(bool), typeof(TouchVirtualizedContentReplaceControl), new PropertyMetadata(true)); static TouchVirtualizedContentReplaceControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TouchVirtualizedContentReplaceControl), new FrameworkPropertyMetadata(typeof(TouchVirtualizedContentReplaceControl))); } public TouchVirtualizedContentReplaceControl() { _replaceContent = new Image(); _updateTimer = new ActionTimer(TimeSpan.FromMilliseconds(100)); Loaded += TouchVirtualizedContentControl_Loaded; } public override void OnApplyTemplate() { base.OnApplyTemplate(); _innerBorder = GetTemplateChild("PART_innerBorder") as Border; _innerBorder.Child = _replaceContent; } private void TouchVirtualizedContentControl_Loaded(object sender, System.Windows.RoutedEventArgs e) { _scrollViewer = this.FindAncestor(); _scrollViewer.Scrolling += _scrollViewer_Scrolling; _parentNameScope = NameScope.GetNameScope(this.FindAncestor()) as INameScopeDictionary; if (DataGrid != null) { DataGrid.SortingChanged += DataGrid_SortingChanged; DataGrid.FilterChanged += DataGrid_FilterChanged; } _location = this.TranslatePoint(new Point(0, 0), _scrollViewer.GetContentGrid()); _scrollViewer.GetContentGrid().SizeChanged += TouchVirtualizedContentControl_SizeChanged; ApplyVirtualization(); _loaded = true; } private void DataGrid_FilterChanged(object sender, EventArgs e) { InvalidateVirtualization(); } private void DataGrid_SortingChanged(object sender, EventArgs e) { InvalidateVirtualization(); } private void TouchVirtualizedContentControl_SizeChanged(object sender, SizeChangedEventArgs e) { InvalidateVirtualization(); } private void _scrollViewer_Scrolling(object sender, DoubleValueChangedEventArgs e) { if (_loaded) { ApplyVirtualization(); } } private void InvalidateVirtualization() { _updateTimer.ResetReplace(() => { Dispatcher.Invoke(new Action(() => { _location = this.TranslatePoint(new Point(0, 0), _scrollViewer.GetContentGrid()); ApplyVirtualization(); })); }); } private void ApplyVirtualization() { if (!Disconnect && _element != null) { _updateTimer.Dispose(); return; } var _border_viewport = _scrollViewer.GetViewportBorder(); if (CanMovePosition) { _location = this.TranslatePoint(new Point(0, 0), _scrollViewer.GetContentGrid()); } Rect bounds = new Rect(_location.X, _location.Y, ActualWidth, ActualHeight); Rect rect = new Rect(0.0, _scrollViewer.GetScrollPosition(), _border_viewport.ActualWidth, _border_viewport.ActualHeight); if (_innerBorder != null) { if (bounds.IntersectsWith(rect)) { if (Disconnect || _element == null) { if (_innerBorder.Child == _replaceContent || _element == null) { _element = Content.LoadContent() as FrameworkElement; if (_parentNameScope != null) { NameScope.SetNameScope(_element, _parentNameScope); } _innerBorder.Child = _element; _innerBorder.Height = double.NaN; } } } else { if (Disconnect) { if (_innerBorder.Child == _element) { double height = _element != null ? _element.ActualHeight : MinHeight; _innerBorder.Child = _replaceContent; _innerBorder.Height = height; } } } } } } }