This commit is contained in:
2025-08-23 21:39:21 +08:00
parent 7bac32e3c4
commit f67b4db4ba
562 changed files with 37981 additions and 38280 deletions
@@ -0,0 +1,167 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace InkCanvasForClass.IccInkCanvas.Utils.Threading
{
/// <summary>
/// The VisualTargetPresentationSource represents the root
/// of a visual subtree owned by a different thread that the
/// visual tree in which is is displayed.
/// </summary>
/// <remarks>
/// A HostVisual belongs to the same UI thread that owns the
/// visual tree in which it resides.
///
/// A HostVisual can reference a VisualTarget owned by another
/// thread.
///
/// A VisualTarget has a root visual.
///
/// VisualTargetPresentationSource wraps the VisualTarget and
/// enables basic functionality like Loaded, which depends on
/// a PresentationSource being available.
/// </remarks>
public class VisualTargetPresentationSource : PresentationSource, IDisposable
{
public VisualTargetPresentationSource(HostVisual hostVisual)
{
_visualTarget = new VisualTarget(hostVisual);
}
public override Visual RootVisual
{
get => _visualTarget.RootVisual;
set
{
if (IsDisposed)
{
throw new ObjectDisposedException("VisualTarget");
}
var oldRoot = _visualTarget.RootVisual;
// Set the root visual of the VisualTarget. This visual will
// now be used to visually compose the scene.
_visualTarget.RootVisual = value;
// Hook the SizeChanged event on framework elements for all
// future changed to the layout size of our root, and manually
// trigger a size change.
if (oldRoot is FrameworkElement oldRootFe)
{
oldRootFe.SizeChanged -= root_SizeChanged;
}
if (value is FrameworkElement rootFe)
{
rootFe.SizeChanged += root_SizeChanged;
rootFe.DataContext = _dataContext;
if (_propertyName != null)
{
var myBinding = new Binding(_propertyName)
{
Source = _dataContext
};
rootFe.SetBinding(TextBlock.TextProperty, myBinding);
}
}
// Tell the PresentationSource that the root visual has
// changed. This kicks off a bunch of stuff like the
// Loaded event.
RootChanged(oldRoot, value);
// Kickoff layout...
if (value is UIElement rootElement)
{
rootElement.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
rootElement.Arrange(new Rect(rootElement.DesiredSize));
}
}
}
public object DataContext
{
get => _dataContext;
set
{
if (IsDisposed)
{
throw new ObjectDisposedException("VisualTarget");
}
if (_dataContext == value)
{
return;
}
_dataContext = value;
if (_visualTarget.RootVisual is FrameworkElement rootElement)
{
rootElement.DataContext = _dataContext;
}
}
}
public string PropertyName
{
get => _propertyName;
set
{
if (IsDisposed)
{
throw new ObjectDisposedException("VisualTarget");
}
_propertyName = value;
if (_visualTarget.RootVisual is TextBlock rootElement)
{
if (!rootElement.CheckAccess())
{
throw new InvalidOperationException("What?");
}
var myBinding = new Binding(_propertyName)
{
Source = _dataContext
};
rootElement.SetBinding(TextBlock.TextProperty, myBinding);
}
}
}
public event SizeChangedEventHandler SizeChanged;
public override bool IsDisposed => _isDisposed;
protected override CompositionTarget GetCompositionTargetCore()
{
return _visualTarget;
}
private void root_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (IsDisposed)
{
return;
}
SizeChanged?.Invoke(this, e);
}
private readonly VisualTarget _visualTarget;
private object _dataContext;
private string _propertyName;
private bool _isDisposed;
public void Dispose()
{
_visualTarget?.Dispose();
_isDisposed = true;
}
}
}