Changed license to Apache License 2.0
This commit is contained in:
parent
857917aad5
commit
0037b7de46
47 changed files with 5942 additions and 5849 deletions
105
Source/ContainerListView/ContainerListView.Designer.cs
generated
105
Source/ContainerListView/ContainerListView.Designer.cs
generated
|
@ -1,53 +1,52 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2019 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace Nuclex.Windows.Forms {
|
||||
|
||||
partial class ContainerListView {
|
||||
|
||||
/// <summary>Required designer variable.</summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>Clean up any resources being used.</summary>
|
||||
/// <param name="disposing">
|
||||
/// true if managed resources should be disposed; otherwise, false.
|
||||
/// </param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Windows.Forms
|
||||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
namespace Nuclex.Windows.Forms {
|
||||
|
||||
partial class ContainerListView {
|
||||
|
||||
/// <summary>Required designer variable.</summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>Clean up any resources being used.</summary>
|
||||
/// <param name="disposing">
|
||||
/// true if managed resources should be disposed; otherwise, false.
|
||||
/// </param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if(disposing && (components != null)) {
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Windows.Forms
|
||||
|
|
|
@ -1,83 +1,82 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2019 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Nuclex.Support;
|
||||
|
||||
namespace Nuclex.Windows.Forms {
|
||||
|
||||
/// <summary>Unit Test for the control container list view</summary>
|
||||
[TestFixture, Explicit]
|
||||
public class ContainerListViewTest {
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the asynchronous progress bar's constructor is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestConstructor() {
|
||||
using(ContainerListView listView = new ContainerListView()) {
|
||||
|
||||
// Let the control create its window handle
|
||||
listView.CreateControl();
|
||||
listView.Columns.Add("Numeric");
|
||||
listView.Columns.Add("Spelled");
|
||||
listView.Columns.Add("Nonsense");
|
||||
|
||||
addRow(listView, "1", "One");
|
||||
addRow(listView, "2", "Two");
|
||||
addRow(listView, "3", "Three");
|
||||
|
||||
using(CheckBox checkBox = new CheckBox()) {
|
||||
listView.EmbeddedControls.Add(new ListViewEmbeddedControl(checkBox, 2, 0));
|
||||
listView.EmbeddedControls.Clear();
|
||||
|
||||
listView.Refresh();
|
||||
|
||||
ListViewEmbeddedControl embeddedControl = new ListViewEmbeddedControl(
|
||||
checkBox, 2, 0
|
||||
);
|
||||
listView.EmbeddedControls.Add(embeddedControl);
|
||||
listView.EmbeddedControls.Remove(embeddedControl);
|
||||
|
||||
listView.Refresh();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Adds a row to a control container list view</summary>
|
||||
/// <param name="listView">List view control the row will be added to</param>
|
||||
/// <param name="columns">Values that will appear in the individual columns</param>
|
||||
private void addRow(ContainerListView listView, params string[] columns) {
|
||||
listView.Items.Add(new ListViewItem(columns));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Windows.Forms
|
||||
|
||||
#endif // UNITTEST
|
||||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Nuclex.Support;
|
||||
|
||||
namespace Nuclex.Windows.Forms {
|
||||
|
||||
/// <summary>Unit Test for the control container list view</summary>
|
||||
[TestFixture, Explicit]
|
||||
public class ContainerListViewTest {
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the asynchronous progress bar's constructor is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestConstructor() {
|
||||
using(ContainerListView listView = new ContainerListView()) {
|
||||
|
||||
// Let the control create its window handle
|
||||
listView.CreateControl();
|
||||
listView.Columns.Add("Numeric");
|
||||
listView.Columns.Add("Spelled");
|
||||
listView.Columns.Add("Nonsense");
|
||||
|
||||
addRow(listView, "1", "One");
|
||||
addRow(listView, "2", "Two");
|
||||
addRow(listView, "3", "Three");
|
||||
|
||||
using(CheckBox checkBox = new CheckBox()) {
|
||||
listView.EmbeddedControls.Add(new ListViewEmbeddedControl(checkBox, 2, 0));
|
||||
listView.EmbeddedControls.Clear();
|
||||
|
||||
listView.Refresh();
|
||||
|
||||
ListViewEmbeddedControl embeddedControl = new ListViewEmbeddedControl(
|
||||
checkBox, 2, 0
|
||||
);
|
||||
listView.EmbeddedControls.Add(embeddedControl);
|
||||
listView.EmbeddedControls.Remove(embeddedControl);
|
||||
|
||||
listView.Refresh();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Adds a row to a control container list view</summary>
|
||||
/// <param name="listView">List view control the row will be added to</param>
|
||||
/// <param name="columns">Values that will appear in the individual columns</param>
|
||||
private void addRow(ContainerListView listView, params string[] columns) {
|
||||
listView.Items.Add(new ListViewItem(columns));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Windows.Forms
|
||||
|
||||
#endif // UNITTEST
|
||||
|
|
|
@ -1,247 +1,246 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2019 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Nuclex.Support.Collections;
|
||||
|
||||
namespace Nuclex.Windows.Forms {
|
||||
|
||||
/// <summary>ListView allowing for other controls to be embedded in its cells</summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// There basically were two possible design choices: Provide a specialized
|
||||
/// ListViewSubItem that carries a Control instead of a string or manage the
|
||||
/// embedded controls seperate of the ListView's items.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The first option requires a complete rewrite of the ListViewItem class
|
||||
/// and its related support classes, all of which are surprisingly large and
|
||||
/// complex. Thus, I chose the less clean but more doable latter option.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This control is useful for simple item lists where you want to provide
|
||||
/// a combobox, checkbox or other control to the user for a certain column.
|
||||
/// It will not perform well for lists with hundreds of items since it
|
||||
/// requires a control to be created per row and management of the embedded
|
||||
/// controls is designed for limited usage.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public partial class ContainerListView : System.Windows.Forms.ListView {
|
||||
|
||||
/// <summary>Message sent to a control to let it paint itself</summary>
|
||||
private const int WM_PAINT = 0x000F;
|
||||
|
||||
/// <summary>Initializes a new ContainerListView</summary>
|
||||
public ContainerListView() {
|
||||
this.embeddedControlClickedDelegate = new EventHandler(embeddedControlClicked);
|
||||
|
||||
this.embeddedControls = new ObservableList<ListViewEmbeddedControl>();
|
||||
this.embeddedControls.ItemAdded +=
|
||||
new EventHandler<ItemEventArgs<ListViewEmbeddedControl>>(embeddedControlAdded);
|
||||
this.embeddedControls.ItemRemoved +=
|
||||
new EventHandler<ItemEventArgs<ListViewEmbeddedControl>>(embeddedControlRemoved);
|
||||
this.embeddedControls.Clearing += new EventHandler(embeddedControlsClearing);
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
// Eliminate flickering
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
|
||||
base.View = View.Details;
|
||||
|
||||
this.columnHeaderHeight = Font.Height;
|
||||
}
|
||||
|
||||
/// <summary>Controls being embedded in the ListView</summary>
|
||||
public ICollection<ListViewEmbeddedControl> EmbeddedControls {
|
||||
get { return this.embeddedControls; }
|
||||
}
|
||||
|
||||
/// <summary>Updates the controls embeded into the list view</summary>
|
||||
public void UpdateEmbeddedControls() {
|
||||
if(View != View.Details) {
|
||||
for(int index = 0; index < this.embeddedControls.Count; ++index) {
|
||||
this.embeddedControls[index].Control.Visible = false;
|
||||
}
|
||||
} else {
|
||||
for(int index = 0; index < this.embeddedControls.Count; ++index) {
|
||||
ListViewEmbeddedControl embeddedControl = this.embeddedControls[index];
|
||||
|
||||
Rectangle cellBounds = this.GetSubItemBounds(
|
||||
Items[embeddedControl.Row], embeddedControl.Column
|
||||
);
|
||||
|
||||
bool intersectsColumnHeader =
|
||||
(base.HeaderStyle != ColumnHeaderStyle.None) &&
|
||||
(cellBounds.Top < base.Font.Height);
|
||||
|
||||
embeddedControl.Control.Visible = !intersectsColumnHeader;
|
||||
embeddedControl.Control.Bounds = cellBounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Calculates the boundaries of a cell in the list view</summary>
|
||||
/// <param name="item">Item in the list view from which to calculate the cell</param>
|
||||
/// <param name="subItem">Index der cell whose boundaries to calculate</param>
|
||||
/// <returns>The boundaries of the specified list view cell</returns>
|
||||
/// <exception cref="IndexOutOfRangeException">
|
||||
/// When the specified sub item index is not in the range of valid sub items
|
||||
/// </exception>
|
||||
protected Rectangle GetSubItemBounds(ListViewItem item, int subItem) {
|
||||
int[] order = GetColumnOrder();
|
||||
if(order == null) { // No Columns
|
||||
return Rectangle.Empty;
|
||||
}
|
||||
|
||||
if(subItem >= order.Length) {
|
||||
throw new IndexOutOfRangeException("SubItem " + subItem + " out of range");
|
||||
}
|
||||
|
||||
// Determine the border of the entire ListViewItem, including all sub items
|
||||
Rectangle itemBounds = item.GetBounds(ItemBoundsPortion.Entire);
|
||||
int subItemX = itemBounds.Left;
|
||||
|
||||
// Find the horizontal position of the sub item. Because the column order can vary,
|
||||
// we need to use Columns[order[i]] instead of simply doing Columns[i] here!
|
||||
ColumnHeader columnHeader;
|
||||
int i;
|
||||
for(i = 0; i < order.Length; ++i) {
|
||||
columnHeader = this.Columns[order[i]];
|
||||
if(columnHeader.Index == subItem) {
|
||||
break;
|
||||
}
|
||||
|
||||
subItemX += columnHeader.Width;
|
||||
}
|
||||
|
||||
return new Rectangle(
|
||||
subItemX, itemBounds.Top, this.Columns[order[i]].Width, itemBounds.Height
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Responds to window messages sent by the operating system</summary>
|
||||
/// <param name="message">Window message that will be processed</param>
|
||||
protected override void WndProc(ref Message message) {
|
||||
switch(message.Msg) {
|
||||
case WM_PAINT: {
|
||||
UpdateEmbeddedControls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
base.WndProc(ref message);
|
||||
}
|
||||
|
||||
/// <summary>Called when the list of embedded controls has been cleared</summary>
|
||||
/// <param name="sender">Collection that has been cleared of its controls</param>
|
||||
/// <param name="arguments">Not used</param>
|
||||
private void embeddedControlsClearing(object sender, EventArgs arguments) {
|
||||
this.BeginUpdate();
|
||||
try {
|
||||
foreach(ListViewEmbeddedControl embeddedControl in this.embeddedControls) {
|
||||
embeddedControl.Control.Click -= this.embeddedControlClickedDelegate;
|
||||
this.Controls.Remove(embeddedControl.Control);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.EndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Called when a control gets removed from the embedded controls list</summary>
|
||||
/// <param name="sender">List from which the control has been removed</param>
|
||||
/// <param name="arguments">
|
||||
/// Event arguments providing a reference to the removed control
|
||||
/// </param>
|
||||
private void embeddedControlAdded(
|
||||
object sender, ItemEventArgs<ListViewEmbeddedControl> arguments
|
||||
) {
|
||||
arguments.Item.Control.Click += this.embeddedControlClickedDelegate;
|
||||
this.Controls.Add(arguments.Item.Control);
|
||||
}
|
||||
|
||||
/// <summary>Called when a control gets added to the embedded controls list</summary>
|
||||
/// <param name="sender">List to which the control has been added</param>
|
||||
/// <param name="arguments">
|
||||
/// Event arguments providing a reference to the added control
|
||||
/// </param>
|
||||
private void embeddedControlRemoved(
|
||||
object sender, ItemEventArgs<ListViewEmbeddedControl> arguments
|
||||
) {
|
||||
if(this.Controls.Contains(arguments.Item.Control)) {
|
||||
arguments.Item.Control.Click -= this.embeddedControlClickedDelegate;
|
||||
this.Controls.Remove(arguments.Item.Control);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Called when an embedded control has been clicked on</summary>
|
||||
/// <param name="sender">Embedded control that has been clicked</param>
|
||||
/// <param name="arguments">Not used</param>
|
||||
private void embeddedControlClicked(object sender, EventArgs arguments) {
|
||||
this.BeginUpdate();
|
||||
|
||||
try {
|
||||
SelectedItems.Clear();
|
||||
|
||||
foreach(ListViewEmbeddedControl embeddedControl in this.embeddedControls) {
|
||||
if(ReferenceEquals(embeddedControl.Control, sender)) {
|
||||
if((embeddedControl.Row > 0) && (embeddedControl.Row < Items.Count)) {
|
||||
Items[embeddedControl.Row].Selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.EndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Obtains the current column order of the list</summary>
|
||||
/// <returns>An array indicating the order of the list's columns</returns>
|
||||
private int[] GetColumnOrder() {
|
||||
int[] order = new int[this.Columns.Count];
|
||||
|
||||
for(int index = 0; index < this.Columns.Count; ++index) {
|
||||
order[this.Columns[index].DisplayIndex] = index;
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
/// <summary>Height of the list view's column header</summary>
|
||||
private int columnHeaderHeight;
|
||||
/// <summary>Event handler for when embedded controls are clicked on</summary>
|
||||
private EventHandler embeddedControlClickedDelegate;
|
||||
/// <summary>Controls being embedded in this ListView</summary>
|
||||
private ObservableList<ListViewEmbeddedControl> embeddedControls;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Windows.Forms
|
||||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Nuclex.Support.Collections;
|
||||
|
||||
namespace Nuclex.Windows.Forms {
|
||||
|
||||
/// <summary>ListView allowing for other controls to be embedded in its cells</summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// There basically were two possible design choices: Provide a specialized
|
||||
/// ListViewSubItem that carries a Control instead of a string or manage the
|
||||
/// embedded controls seperate of the ListView's items.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The first option requires a complete rewrite of the ListViewItem class
|
||||
/// and its related support classes, all of which are surprisingly large and
|
||||
/// complex. Thus, I chose the less clean but more doable latter option.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This control is useful for simple item lists where you want to provide
|
||||
/// a combobox, checkbox or other control to the user for a certain column.
|
||||
/// It will not perform well for lists with hundreds of items since it
|
||||
/// requires a control to be created per row and management of the embedded
|
||||
/// controls is designed for limited usage.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public partial class ContainerListView : System.Windows.Forms.ListView {
|
||||
|
||||
/// <summary>Message sent to a control to let it paint itself</summary>
|
||||
private const int WM_PAINT = 0x000F;
|
||||
|
||||
/// <summary>Initializes a new ContainerListView</summary>
|
||||
public ContainerListView() {
|
||||
this.embeddedControlClickedDelegate = new EventHandler(embeddedControlClicked);
|
||||
|
||||
this.embeddedControls = new ObservableList<ListViewEmbeddedControl>();
|
||||
this.embeddedControls.ItemAdded +=
|
||||
new EventHandler<ItemEventArgs<ListViewEmbeddedControl>>(embeddedControlAdded);
|
||||
this.embeddedControls.ItemRemoved +=
|
||||
new EventHandler<ItemEventArgs<ListViewEmbeddedControl>>(embeddedControlRemoved);
|
||||
this.embeddedControls.Clearing += new EventHandler(embeddedControlsClearing);
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
// Eliminate flickering
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
|
||||
base.View = View.Details;
|
||||
|
||||
this.columnHeaderHeight = Font.Height;
|
||||
}
|
||||
|
||||
/// <summary>Controls being embedded in the ListView</summary>
|
||||
public ICollection<ListViewEmbeddedControl> EmbeddedControls {
|
||||
get { return this.embeddedControls; }
|
||||
}
|
||||
|
||||
/// <summary>Updates the controls embeded into the list view</summary>
|
||||
public void UpdateEmbeddedControls() {
|
||||
if(View != View.Details) {
|
||||
for(int index = 0; index < this.embeddedControls.Count; ++index) {
|
||||
this.embeddedControls[index].Control.Visible = false;
|
||||
}
|
||||
} else {
|
||||
for(int index = 0; index < this.embeddedControls.Count; ++index) {
|
||||
ListViewEmbeddedControl embeddedControl = this.embeddedControls[index];
|
||||
|
||||
Rectangle cellBounds = this.GetSubItemBounds(
|
||||
Items[embeddedControl.Row], embeddedControl.Column
|
||||
);
|
||||
|
||||
bool intersectsColumnHeader =
|
||||
(base.HeaderStyle != ColumnHeaderStyle.None) &&
|
||||
(cellBounds.Top < base.Font.Height);
|
||||
|
||||
embeddedControl.Control.Visible = !intersectsColumnHeader;
|
||||
embeddedControl.Control.Bounds = cellBounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Calculates the boundaries of a cell in the list view</summary>
|
||||
/// <param name="item">Item in the list view from which to calculate the cell</param>
|
||||
/// <param name="subItem">Index der cell whose boundaries to calculate</param>
|
||||
/// <returns>The boundaries of the specified list view cell</returns>
|
||||
/// <exception cref="IndexOutOfRangeException">
|
||||
/// When the specified sub item index is not in the range of valid sub items
|
||||
/// </exception>
|
||||
protected Rectangle GetSubItemBounds(ListViewItem item, int subItem) {
|
||||
int[] order = GetColumnOrder();
|
||||
if(order == null) { // No Columns
|
||||
return Rectangle.Empty;
|
||||
}
|
||||
|
||||
if(subItem >= order.Length) {
|
||||
throw new IndexOutOfRangeException("SubItem " + subItem + " out of range");
|
||||
}
|
||||
|
||||
// Determine the border of the entire ListViewItem, including all sub items
|
||||
Rectangle itemBounds = item.GetBounds(ItemBoundsPortion.Entire);
|
||||
int subItemX = itemBounds.Left;
|
||||
|
||||
// Find the horizontal position of the sub item. Because the column order can vary,
|
||||
// we need to use Columns[order[i]] instead of simply doing Columns[i] here!
|
||||
ColumnHeader columnHeader;
|
||||
int i;
|
||||
for(i = 0; i < order.Length; ++i) {
|
||||
columnHeader = this.Columns[order[i]];
|
||||
if(columnHeader.Index == subItem) {
|
||||
break;
|
||||
}
|
||||
|
||||
subItemX += columnHeader.Width;
|
||||
}
|
||||
|
||||
return new Rectangle(
|
||||
subItemX, itemBounds.Top, this.Columns[order[i]].Width, itemBounds.Height
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Responds to window messages sent by the operating system</summary>
|
||||
/// <param name="message">Window message that will be processed</param>
|
||||
protected override void WndProc(ref Message message) {
|
||||
switch(message.Msg) {
|
||||
case WM_PAINT: {
|
||||
UpdateEmbeddedControls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
base.WndProc(ref message);
|
||||
}
|
||||
|
||||
/// <summary>Called when the list of embedded controls has been cleared</summary>
|
||||
/// <param name="sender">Collection that has been cleared of its controls</param>
|
||||
/// <param name="arguments">Not used</param>
|
||||
private void embeddedControlsClearing(object sender, EventArgs arguments) {
|
||||
this.BeginUpdate();
|
||||
try {
|
||||
foreach(ListViewEmbeddedControl embeddedControl in this.embeddedControls) {
|
||||
embeddedControl.Control.Click -= this.embeddedControlClickedDelegate;
|
||||
this.Controls.Remove(embeddedControl.Control);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.EndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Called when a control gets removed from the embedded controls list</summary>
|
||||
/// <param name="sender">List from which the control has been removed</param>
|
||||
/// <param name="arguments">
|
||||
/// Event arguments providing a reference to the removed control
|
||||
/// </param>
|
||||
private void embeddedControlAdded(
|
||||
object sender, ItemEventArgs<ListViewEmbeddedControl> arguments
|
||||
) {
|
||||
arguments.Item.Control.Click += this.embeddedControlClickedDelegate;
|
||||
this.Controls.Add(arguments.Item.Control);
|
||||
}
|
||||
|
||||
/// <summary>Called when a control gets added to the embedded controls list</summary>
|
||||
/// <param name="sender">List to which the control has been added</param>
|
||||
/// <param name="arguments">
|
||||
/// Event arguments providing a reference to the added control
|
||||
/// </param>
|
||||
private void embeddedControlRemoved(
|
||||
object sender, ItemEventArgs<ListViewEmbeddedControl> arguments
|
||||
) {
|
||||
if(this.Controls.Contains(arguments.Item.Control)) {
|
||||
arguments.Item.Control.Click -= this.embeddedControlClickedDelegate;
|
||||
this.Controls.Remove(arguments.Item.Control);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Called when an embedded control has been clicked on</summary>
|
||||
/// <param name="sender">Embedded control that has been clicked</param>
|
||||
/// <param name="arguments">Not used</param>
|
||||
private void embeddedControlClicked(object sender, EventArgs arguments) {
|
||||
this.BeginUpdate();
|
||||
|
||||
try {
|
||||
SelectedItems.Clear();
|
||||
|
||||
foreach(ListViewEmbeddedControl embeddedControl in this.embeddedControls) {
|
||||
if(ReferenceEquals(embeddedControl.Control, sender)) {
|
||||
if((embeddedControl.Row > 0) && (embeddedControl.Row < Items.Count)) {
|
||||
Items[embeddedControl.Row].Selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.EndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Obtains the current column order of the list</summary>
|
||||
/// <returns>An array indicating the order of the list's columns</returns>
|
||||
private int[] GetColumnOrder() {
|
||||
int[] order = new int[this.Columns.Count];
|
||||
|
||||
for(int index = 0; index < this.Columns.Count; ++index) {
|
||||
order[this.Columns[index].DisplayIndex] = index;
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
/// <summary>Height of the list view's column header</summary>
|
||||
private int columnHeaderHeight;
|
||||
/// <summary>Event handler for when embedded controls are clicked on</summary>
|
||||
private EventHandler embeddedControlClickedDelegate;
|
||||
/// <summary>Controls being embedded in this ListView</summary>
|
||||
private ObservableList<ListViewEmbeddedControl> embeddedControls;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Windows.Forms
|
||||
|
|
|
@ -1,64 +1,63 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2019 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Nuclex.Windows.Forms {
|
||||
|
||||
/// <summary>Stores informations about an embedded control</summary>
|
||||
public class ListViewEmbeddedControl {
|
||||
|
||||
/// <summary>Initializes a new embedded control holder</summary>
|
||||
/// <param name="control">Control being embedded in a list view</param>
|
||||
/// <param name="row">List row at which the control will be embedded</param>
|
||||
/// <param name="column">List column at which the control will be embedded</param>
|
||||
public ListViewEmbeddedControl(Control control, int row, int column) {
|
||||
this.control = control;
|
||||
this.row = row;
|
||||
this.column = column;
|
||||
}
|
||||
|
||||
/// <summary>Control that is being embedded in the ListView</summary>
|
||||
public Control Control {
|
||||
get { return this.control; }
|
||||
}
|
||||
|
||||
/// <summary>Row the control has been embedded in</summary>
|
||||
public int Row {
|
||||
get { return this.row; }
|
||||
}
|
||||
|
||||
/// <summary>Column the control has been embedded in</summary>
|
||||
public int Column {
|
||||
get { return this.column; }
|
||||
}
|
||||
|
||||
/// <summary>Embedded control</summary>
|
||||
private Control control;
|
||||
/// <summary>Row where the control is embedded</summary>
|
||||
private int row;
|
||||
/// <summary>Column where the control is embedded</summary>
|
||||
private int column;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Windows.Forms
|
||||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Nuclex.Windows.Forms {
|
||||
|
||||
/// <summary>Stores informations about an embedded control</summary>
|
||||
public class ListViewEmbeddedControl {
|
||||
|
||||
/// <summary>Initializes a new embedded control holder</summary>
|
||||
/// <param name="control">Control being embedded in a list view</param>
|
||||
/// <param name="row">List row at which the control will be embedded</param>
|
||||
/// <param name="column">List column at which the control will be embedded</param>
|
||||
public ListViewEmbeddedControl(Control control, int row, int column) {
|
||||
this.control = control;
|
||||
this.row = row;
|
||||
this.column = column;
|
||||
}
|
||||
|
||||
/// <summary>Control that is being embedded in the ListView</summary>
|
||||
public Control Control {
|
||||
get { return this.control; }
|
||||
}
|
||||
|
||||
/// <summary>Row the control has been embedded in</summary>
|
||||
public int Row {
|
||||
get { return this.row; }
|
||||
}
|
||||
|
||||
/// <summary>Column the control has been embedded in</summary>
|
||||
public int Column {
|
||||
get { return this.column; }
|
||||
}
|
||||
|
||||
/// <summary>Embedded control</summary>
|
||||
private Control control;
|
||||
/// <summary>Row where the control is embedded</summary>
|
||||
private int row;
|
||||
/// <summary>Column where the control is embedded</summary>
|
||||
private int column;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Windows.Forms
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue