|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace System.Windows.Forms;
/// <summary>
/// Represents a control of a task dialog.
/// </summary>
public abstract class TaskDialogControl
{
// Disallow inheritance by specifying a private protected constructor.
private protected TaskDialogControl()
{
}
/// <summary>
/// Gets or sets the object that contains data about the control.
/// </summary>
/// <value>
/// An <see cref="object"/> that contains data about the control.
/// The default is <see langword="null"/>.
/// </value>
public object? Tag { get; set; }
/// <summary>
/// Gets the <see cref="TaskDialogPage"/> instance which this control
/// is currently bound to.
/// </summary>
/// <value>
/// The <see cref="TaskDialogPage"/> instance which this control is bound to, or
/// <see langword="null"/> if this control is not currently bound.
/// </value>
/// <remarks>
/// <para>
/// A control will be bound to a page while it is being displayed, for exactly the
/// same time as the returned page is bound to a dialog that can be retrieved by
/// <see cref="TaskDialogPage.BoundDialog"/>.
/// </para>
/// <para>
/// While a control is bound to a page, you cannot show that control instance using a
/// different <see cref="TaskDialogPage"/> instance at the same time.
/// </para>
/// </remarks>
public TaskDialogPage? BoundPage { get; private set; }
/// <summary>
/// Gets a value that indicates whether the current state of this control
/// allows it to be created in a task dialog when binding it.
/// </summary>
internal virtual bool IsCreatable => true;
/// <summary>
/// Gets or sets a value that indicates whether this control has been created
/// in a bound task dialog.
/// </summary>
internal bool IsCreated { get; private set; }
internal TASKDIALOG_FLAGS Bind(TaskDialogPage page)
{
BoundPage = page.OrThrowIfNull();
// Use the current value of IsCreatable to determine if the control is
// created. This is important because IsCreatable can change while the
// control is displayed (e.g. if it depends on the Text property).
IsCreated = IsCreatable;
return IsCreated ? BindCore() : default;
}
internal void Unbind()
{
if (IsCreated)
{
UnbindCore();
}
IsCreated = false;
BoundPage = null;
}
/// <summary>
/// Applies initialization after the task dialog is displayed or navigated.
/// </summary>
internal void ApplyInitialization()
{
// Only apply the initialization if the control is actually created.
if (IsCreated)
{
ApplyInitializationCore();
}
}
/// <summary>
/// When overridden in a derived class, runs additional binding logic and returns
/// flags to be specified before the task dialog is displayed or navigated.
/// </summary>
/// <remarks>
/// <para>
/// This method will only be called if <see cref="IsCreatable"/> returns <see langword="true"/>.
/// </para>
/// </remarks>
/// <returns></returns>
private protected virtual TASKDIALOG_FLAGS BindCore() => default;
/// <summary>
///
/// </summary>
/// <remarks>
/// <para>
/// This method will only be called if <see cref="BindCore"/> was called.
/// </para>
/// </remarks>
private protected virtual void UnbindCore()
{
}
/// <summary>
/// When overridden in a subclass, applies initialization after the task dialog
/// is displayed or navigated.
/// </summary>
/// <remarks>
/// <para>
/// This method will only be called if <see cref="IsCreatable"/> returns <see langword="true"/>.
/// </para>
/// </remarks>
private protected virtual void ApplyInitializationCore()
{
}
private protected void DenyIfBound() => BoundPage?.DenyIfBound();
private protected void DenyIfWaitingForInitialization() => BoundPage?.DenyIfWaitingForInitialization();
private protected void DenyIfNotBoundOrWaitingForInitialization()
{
DenyIfWaitingForInitialization();
if (BoundPage is null)
{
throw new InvalidOperationException(SR.TaskDialogControlNotBound);
}
}
private protected void DenyIfBoundAndNotCreated()
{
if (BoundPage is not null && !IsCreated)
{
throw new InvalidOperationException(SR.TaskDialogControlNotCreated);
}
}
}
|