Add initial SplitContainer component

This commit is contained in:
Eilon Lipton 2019-08-16 13:32:58 -07:00
Родитель eac0c6ff9b
Коммит afc32ba73d
7 изменённых файлов: 181 добавлений и 13 удалений

Просмотреть файл

@ -36,7 +36,7 @@ namespace BlinForms.Framework
public override string ToString()
{
return $"Blontrol: Name={Name ?? "<?>"}, Target={TargetControl?.GetType().Name ?? "<?>"}, #Children={Children.Count}";
return $"Bladapter: Name={Name ?? "<?>"}, Target={TargetControl?.GetType().Name ?? "<?>"}, #Children={Children.Count}";
}
internal void ApplyEdits(int componentId, ArrayBuilderSegment<RenderTreeEdit> edits, ArrayRange<RenderTreeFrame> referenceFrames, RenderBatch batch)
@ -134,10 +134,23 @@ namespace BlinForms.Framework
TargetControl = nativeControl;
// Add the new native control to the parent's child controls (the parent adapter is our
// container, so the parent adapter's control is our control's container.
AddChildControl(siblingIndex, TargetControl);
if (nativeControl is ICustomParentingBehavior customChildBehavior)
{
customChildBehavior.SetActualParentControl(Parent.TargetControl);
}
else
{
if (Parent.TargetControl is ICustomParentingBehavior customParentBehavior)
{
AddChildControl(customParentBehavior.GetEffectiveParentControl(), siblingIndex, TargetControl);
}
else
{
// Add the new native control to the parent's child controls (the parent adapter is our
// container, so the parent adapter's control is our control's container.
AddChildControl(Parent.TargetControl, siblingIndex, TargetControl);
}
}
var endIndexExcl = frameIndex + frames[frameIndex].ElementSubtreeLength;
for (var descendantIndex = frameIndex + 1; descendantIndex < endIndexExcl; descendantIndex++)
@ -215,19 +228,19 @@ namespace BlinForms.Framework
}
}
private void AddChildControl(int siblingIndex, Control childControl)
private static void AddChildControl(Control parentControl, int siblingIndex, Control childControl)
{
if (siblingIndex <= Parent.TargetControl.Controls.Count)
if (siblingIndex <= parentControl.Controls.Count)
{
// WinForms ControlCollection doesn't support Insert(), so add the new child at the end,
// and then re-order the collection to move the control to the correct index.
Parent.TargetControl.Controls.Add(childControl);
Parent.TargetControl.Controls.SetChildIndex(childControl, siblingIndex);
parentControl.Controls.Add(childControl);
parentControl.Controls.SetChildIndex(childControl, siblingIndex);
}
else
{
Debug.WriteLine($"WARNING: {nameof(AddChildControl)} called with {nameof(siblingIndex)}={siblingIndex}, but Parent.TargetControl.Controls.Count={Parent.TargetControl.Controls.Count}");
Parent.TargetControl.Controls.Add(childControl);
Debug.WriteLine($"WARNING: {nameof(AddChildControl)} called with {nameof(siblingIndex)}={siblingIndex}, but parentControl.Controls.Count={parentControl.Controls.Count}");
parentControl.Controls.Add(childControl);
}
}

Просмотреть файл

@ -0,0 +1,15 @@
using System.Windows.Forms;
namespace BlinForms.Framework.Controls
{
/// <summary>
/// Indicates that a control has a custom behavior for determining where child controls should be parented to.
/// For example, a SplitContainer control has built-in immutable children, and should not have those children
/// created directly.
/// </summary>
internal interface ICustomParentingBehavior
{
void SetActualParentControl(Control parentControl);
Control GetEffectiveParentControl();
}
}

Просмотреть файл

@ -0,0 +1,24 @@
using System;
using System.Windows.Forms;
namespace BlinForms.Framework.Controls
{
public class PlaceholderControl : Control, ICustomParentingBehavior
{
private Control _parentControl;
public string State { get; set; }
public Control GetEffectiveParentControl()
{
var parentSplitter = (System.Windows.Forms.SplitContainer)_parentControl;
var containerPanel = State == "Panel1" ? parentSplitter.Panel1 : State == "Panel2" ? parentSplitter.Panel2 : throw new InvalidOperationException("Invalid panel state!!!");
return containerPanel;
}
public void SetActualParentControl(Control parentControl)
{
_parentControl = parentControl;
}
}
}

Просмотреть файл

@ -0,0 +1,44 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.RenderTree;
using System.Windows.Forms;
namespace BlinForms.Framework.Controls
{
public class SplitContainer : FormsComponentBase
{
static SplitContainer()
{
BlontrolAdapter.KnownElements.Add(typeof(SplitContainer).FullName, renderer => new BlazorSplitContainer());
}
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public Orientation Orientation { get; set; }
protected override void RenderAttributes(RenderTreeBuilder builder)
{
builder.AddAttribute(1, nameof(Orientation), (int)Orientation);
}
protected override void RenderContents(RenderTreeBuilder builder)
{
builder.AddContent(1000, ChildContent);
}
class BlazorSplitContainer : System.Windows.Forms.SplitContainer, IBlazorNativeControl
{
public void ApplyAttribute(ulong attributeEventHandlerId, string attributeName, object attributeValue, string attributeEventUpdatesAttributeName)
{
switch (attributeName)
{
case nameof(Orientation):
if ((attributeValue as string) != "0")
Orientation = (Orientation)int.Parse((string)attributeValue);
break;
default:
FormsComponentBase.ApplyAttribute(this, attributeEventHandlerId, attributeName, attributeValue, attributeEventUpdatesAttributeName);
break;
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.RenderTree;
namespace BlinForms.Framework.Controls
{
public class SplitterPanel1 : FormsComponentBase
{
static SplitterPanel1()
{
BlontrolAdapter.KnownElements.Add(typeof(SplitterPanel1).FullName, _ => new PlaceholderControl() { State = "Panel1", });
}
[Parameter] public RenderFragment ChildContent { get; set; }
protected override void RenderContents(RenderTreeBuilder builder)
{
builder.AddContent(1000, ChildContent);
}
}
}

Просмотреть файл

@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.RenderTree;
namespace BlinForms.Framework.Controls
{
public class SplitterPanel2 : FormsComponentBase
{
static SplitterPanel2()
{
BlontrolAdapter.KnownElements.Add(typeof(SplitterPanel2).FullName, _ => new PlaceholderControl() { State = "Panel2", });
}
[Parameter] public RenderFragment ChildContent { get; set; }
protected override void RenderContents(RenderTreeBuilder builder)
{
builder.AddContent(1000, ChildContent);
}
}
}

Просмотреть файл

@ -1,7 +1,7 @@
@using BlinForms.Framework.Controls
@using System.Drawing
<Panel Visible="true" BackColor="Color.Red" Top="200" Left="300" Width="300" Height="200" Anchor="@(System.Windows.Forms.AnchorStyles.Right | System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)">
<Panel Visible="true" BackColor="Color.Red" Top="240" Left="300" Width="300" Height="200" Anchor="@(System.Windows.Forms.AnchorStyles.Right | System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)">
<Label Top="50" Left="10" Width="150" Height="23" BackColor="Color.Yellow" Text="This label is nested"></Label>
<TextBox Top="75" Left="20" Height="100" Width="150" Text="Heeeeeeey" Multiline="true" ScrollBars="System.Windows.Forms.ScrollBars.Vertical"></TextBox>
@ -10,7 +10,7 @@
@*<Timer OnTick="@OnTimerTick" />*@
<Button Top="50" Width="300" Text="@("Increment: " + count)" Height="23" OnClick="@IncrementCount" />
<Button Top="50" Width="200" Text="@("Increment: " + count)" Height="23" OnClick="@IncrementCount" />
<Label Top="100" Width="200" Height="23" BackColor="Color.AliceBlue" Text="@("I'm a label: " + labelCount)"></Label>
@ -26,12 +26,44 @@ else
<Label Top="300" Width="200" Height="23" Text="Details NOT visible..."></Label>
}
<SplitContainer Top="340" Left="15" Width="250" Height="100" BackColor="Color.Salmon" Orientation="System.Windows.Forms.Orientation.Horizontal">
<SplitterPanel1>
<Button Width="100" Height="23" BackColor="Color.Aqua" Text="@("Button: " + _splitterButtonValue)" OnClick="@OnSplitterButtonClick"></Button>
</SplitterPanel1>
<SplitterPanel2>
<Label Width="73" Height="23" BackColor="Color.Goldenrod" Text="@("Label: " + _splitterButtonValue)"></Label>
</SplitterPanel2>
</SplitContainer>
@code {
int count = 0;
int labelCount = 0;
bool isDetailsVisible = true;
int _splitterButtonValue = 0;
void OnSplitterButtonClick()
{
_splitterButtonValue++;
}
System.Windows.Forms.ColumnHeader[] _columns = new System.Windows.Forms.ColumnHeader[]
{
new System.Windows.Forms.ColumnHeader()
{
Text = "Tag",
Width = 200,
},
new System.Windows.Forms.ColumnHeader()
{
Text = "Count",
Width = 80,
TextAlign = System.Windows.Forms.HorizontalAlignment.Right,
},
};
void IncrementCount()
{
count++;