Browse Source

Added Control.Initialized.

portable-xaml
Steven Kirk 11 years ago
parent
commit
45b5ec5d8f
  1. 54
      src/Perspex.Controls/Control.cs
  2. 14
      src/Perspex.Controls/IControl.cs
  3. 108
      src/Perspex.SceneGraph/Visual.cs
  4. 28
      tests/Perspex.Controls.UnitTests/ControlTests.cs

54
src/Perspex.Controls/Control.cs

@ -137,6 +137,16 @@ namespace Perspex.Controls
/// </remarks>
public event EventHandler DataContextChanged;
/// <summary>
/// Occurs when the control has finished initialization.
/// </summary>
/// <remarks>
/// The Initialized event indicates that all property values on the control have been set.
/// It occurs when <see cref="ISupportInitialize.EndInit"/> is called when loading the
/// control from markup, or when the control is attached to the visual tree otherwise.
/// </remarks>
public event EventHandler Initialized;
/// <summary>
/// Gets or sets the name of the control.
/// </summary>
@ -233,6 +243,15 @@ namespace Perspex.Controls
set { _dataTemplates = value; }
}
/// <summary>
/// Gets a value that indicates whether the element has finished initialization.
/// </summary>
/// <remarks>
/// For more information about when IsInitialized is set, see the <see cref="Initialized"/>
/// event.
/// </remarks>
public bool IsInitialized { get; private set; }
/// <summary>
/// Gets or sets the styles for the control.
/// </summary>
@ -334,11 +353,20 @@ namespace Perspex.Controls
throw new InvalidOperationException("BeginInit was not called.");
}
if (--_initCount == 0 && _isAttachedToLogicalTree && !_styled)
if (--_initCount == 0)
{
RegisterWithNameScope();
ApplyStyling();
_styled = true;
if (_isAttachedToLogicalTree && !_styled)
{
RegisterWithNameScope();
ApplyStyling();
_styled = true;
}
if (!IsInitialized)
{
IsInitialized = true;
Initialized?.Invoke(this, EventArgs.Empty);
}
}
}
@ -499,6 +527,24 @@ namespace Perspex.Controls
DetachedFromLogicalTree?.Invoke(this, e);
}
/// <inheritdoc/>
protected sealed override void OnAttachedToVisualTreeCore(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTreeCore(e);
if (!IsInitialized)
{
IsInitialized = true;
Initialized?.Invoke(this, EventArgs.Empty);
}
}
/// <inheritdoc/>
protected sealed override void OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTreeCore(e);
}
/// <inheritdoc/>
protected override void OnGotFocus(GotFocusEventArgs e)
{

14
src/Perspex.Controls/IControl.cs

@ -17,14 +17,9 @@ namespace Perspex.Controls
public interface IControl : IVisual, ILogical, ILayoutable, IInputElement, INamed, IStyleable, IStyleHost
{
/// <summary>
/// Raised when the control is attached to a rooted logical tree.
/// Occurs when the control has finished initialization.
/// </summary>
event EventHandler<LogicalTreeAttachmentEventArgs> AttachedToLogicalTree;
/// <summary>
/// Raised when the control is detached from a rooted logical tree.
/// </summary>
event EventHandler<LogicalTreeAttachmentEventArgs> DetachedFromLogicalTree;
event EventHandler Initialized;
/// <summary>
/// Gets or sets the control's styling classes.
@ -41,6 +36,11 @@ namespace Perspex.Controls
/// </summary>
DataTemplates DataTemplates { get; }
/// <summary>
/// Gets a value that indicates whether the element has finished initialization.
/// </summary>
bool IsInitialized { get; }
/// <summary>
/// Gets the control's logical parent.
/// </summary>

108
src/Perspex.SceneGraph/Visual.cs

@ -281,6 +281,60 @@ namespace Perspex
}
}
/// <summary>
/// Calls the <see cref="OnAttachedToVisualTree(VisualTreeAttachmentEventArgs)"/> method
/// for this control and all of its visual descendents.
/// </summary>
/// <param name="e">The event args.</param>
protected virtual void OnAttachedToVisualTreeCore(VisualTreeAttachmentEventArgs e)
{
Logger.Verbose(LogArea.Visual, this, "Attached to visual tree");
VisualRoot = e.Root;
if (RenderTransform != null)
{
RenderTransform.Changed += RenderTransformChanged;
}
OnAttachedToVisualTree(e);
if (VisualChildren != null)
{
foreach (Visual child in VisualChildren.OfType<Visual>())
{
child.OnAttachedToVisualTreeCore(e);
}
}
}
/// <summary>
/// Calls the <see cref="OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs)"/> method
/// for this control and all of its visual descendents.
/// </summary>
/// <param name="e">The event args.</param>
protected virtual void OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e)
{
Logger.Verbose(LogArea.Visual, this, "Detached from visual tree");
VisualRoot = null;
if (RenderTransform != null)
{
RenderTransform.Changed -= RenderTransformChanged;
}
OnDetachedFromVisualTree(e);
if (VisualChildren != null)
{
foreach (Visual child in VisualChildren.OfType<Visual>())
{
child.OnDetachedFromVisualTreeCore(e);
}
}
}
/// <summary>
/// Called when the control is added to a visual tree.
/// </summary>
@ -438,59 +492,5 @@ namespace Perspex
break;
}
}
/// <summary>
/// Calls the <see cref="OnAttachedToVisualTree(VisualTreeAttachmentEventArgs)"/> method
/// for this control and all of its visual descendents.
/// </summary>
/// <param name="e">The event args.</param>
private void OnAttachedToVisualTreeCore(VisualTreeAttachmentEventArgs e)
{
Logger.Verbose(LogArea.Visual, this, "Attached to visual tree");
VisualRoot = e.Root;
if (RenderTransform != null)
{
RenderTransform.Changed += RenderTransformChanged;
}
OnAttachedToVisualTree(e);
if (VisualChildren != null)
{
foreach (Visual child in VisualChildren.OfType<Visual>())
{
child.OnAttachedToVisualTreeCore(e);
}
}
}
/// <summary>
/// Calls the <see cref="OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs)"/> method
/// for this control and all of its visual descendents.
/// </summary>
/// <param name="e">The event args.</param>
private void OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e)
{
Logger.Verbose(LogArea.Visual, this, "Detached from visual tree");
VisualRoot = null;
if (RenderTransform != null)
{
RenderTransform.Changed -= RenderTransformChanged;
}
OnDetachedFromVisualTree(e);
if (VisualChildren != null)
{
foreach (Visual child in VisualChildren.OfType<Visual>())
{
child.OnDetachedFromVisualTreeCore(e);
}
}
}
}
}

28
tests/Perspex.Controls.UnitTests/ControlTests.cs

@ -230,6 +230,34 @@ namespace Perspex.Controls.UnitTests
}
}
[Fact]
public void EndInit_Should_Raise_Initialized()
{
var target = new Border();
var called = false;
target.Initialized += (s, e) => called = true;
((ISupportInitialize)target).BeginInit();
((ISupportInitialize)target).EndInit();
Assert.True(called);
Assert.True(target.IsInitialized);
}
[Fact]
public void Attaching_To_Visual_Tree_Should_Raise_Initialized()
{
var root = new TestRoot();
var target = new Border();
var called = false;
target.Initialized += (s, e) => called = true;
root.Child = target;
Assert.True(called);
Assert.True(target.IsInitialized);
}
private class TestControl : Control
{
public new PerspexObject InheritanceParent => base.InheritanceParent;

Loading…
Cancel
Save