Index: Core/Common/src/Core.Common.Controls.Swf/Core.Common.Controls.Swf.csproj
===================================================================
diff -u -r8cae5d69ac2d4cf678486ac2b457c0dfe97089d5 -r46f5191a65faec434930a191e65f4c23d9ff8cfe
--- Core/Common/src/Core.Common.Controls.Swf/Core.Common.Controls.Swf.csproj (.../Core.Common.Controls.Swf.csproj) (revision 8cae5d69ac2d4cf678486ac2b457c0dfe97089d5)
+++ Core/Common/src/Core.Common.Controls.Swf/Core.Common.Controls.Swf.csproj (.../Core.Common.Controls.Swf.csproj) (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -65,26 +65,6 @@
AllRules.ruleset
-
- False
- ..\..\..\..\lib\DevExpress.Data.v9.3.dll
-
-
- False
- ..\..\..\..\lib\DevExpress.Utils.v9.3.dll
-
-
- False
- ..\..\..\..\lib\DevExpress.XtraEditors.v9.3.dll
-
-
- False
- ..\..\..\..\lib\DevExpress.XtraGrid.v9.3.dll
-
-
- False
- ..\..\..\..\lib\DevExpress.XtraWizard.v9.3.dll
-
..\..\..\..\packages\log4net.2.0.4\lib\net40-full\log4net.dll
True
@@ -103,10 +83,6 @@
-
- False
- ..\..\..\..\lib\TeeChart.dll
-
@@ -116,61 +92,21 @@
Component
-
- UserControl
-
-
-
- UserControl
-
UserControl
FindAndReplaceControl.cs
-
- UserControl
-
-
- ComboBoxTypeEditor.cs
-
Component
-
True
True
Resources.resx
-
-
-
-
-
-
-
-
- UserControl
-
-
- TableView.cs
-
-
-
-
-
-
-
-
-
- Form
-
-
- WizardDialog.cs
-
@@ -185,14 +121,6 @@
Resources.Designer.cs
Designer
-
- TableView.cs
- Designer
-
-
- WizardDialog.cs
- Designer
-
@@ -230,18 +158,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
False
.NET Framework 3.5 SP1 Client Profile
@@ -259,59 +175,11 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\PasteHS.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\information.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\folder.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\edit_replace_all.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\binocular.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\drive.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\computer.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\table_edit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\page_white.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\csv-export.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\DeleteHS1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ Transparantie moet tussen 0 en 100 liggen.
+
+
+ ..\Resources\csv-import.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\edit-replace.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\pin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\CopyHS.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\cross.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\tick.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\funnel-small.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\funnel--minus.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ Argument kan niet de waarde 'null' hebben.
+
+
+ Bestandsnaam moet een extensie hebben.
+
+
+ Argument bevat geen bestandsnaam.
+
+
+ Nieuwe tabel
+
+
+ Kopiëren
+
+
+ Plakken
+
+
+ Verwijderen
+
+
+ Gearceerde stijl wordt niet ondersteund voor exporteren en zal genegeerd worden.
+
+
+ Extensie ({0}) wordt niet ondersteund.
+
+
+ Invoerformaat wordt niet ondersteund. Y moet numeriek zijn maar is van type: {0}.
+
+
+ Ongeldig argument voor databron van gegevensreeks. Biedt u een IEnumerable aan? IList en IListSource worden ondersteund.
+
+
+ Dit programma accepteert alleen {0} als gegevensreeks.
+
+
+ Geen cursor toegewezen aan {0}.
+
+
+ Verschil:
+horizontaal: {0}
+verticaal: {1}
+
+
+ seconden
+
+
+ Actie {0} wordt niet ondersteund door de TableView.
+
+
+ Ongebonden kolommen van type {0} worden niet ondersteund.
+
+
+ Ongeldig rijnummer {0}.
+
+
+ Weet u zeker dat u het volgende element wilt verwijderen: {0}
+
+
+ Kan INodePresenter voor {0} niet vinden. Zorg ervoor dat u de ontbrekende INodePresenter aan de NodePresenters eigenschap van een TreeView heeft toegevoegd.
+
+
+ Kan diagram niet tekenen.
+
+
+ Aantal X-waarden moet gelijk zijn aan het aantal Y-waarden.
+
+
+ Zou geen indices lager dan -1 moeten teruggeven!
+
+
+ Geselecteerde index is buiten bereik van de gevensreeks.
+
+
+ 'LastSelectedSeries' moet gezet zijn voordat 'SelectedPointIndex' wordt gezet.
+
+
+ Onbekende TeeChart gegevensreeks: houdt geen verband met een bekende ChartSeries.
+
+
+ Verwijderen is niet geïmplementeerd voor dit type databron.
+
+
+ X-waarde wordt vastgelegd (linker limiet) {0} => {1}.
+
+
+ X-waarde wordt vastgelegd (rechter limiet) {0} => {1}.
+
+
+ Niet te klonen subelementen in menu-element.
+
+
+ De eigenschap 'DockStyle' van de inklapbare splitser kan geen waarde 'Filled' of 'None' hebben.
+
+
+ Er is een kritieke fout opgetreden. Ringtoets moet herstart worden.
+
+
+ {0} tot {1}
+
+
+ Er is een fout opgetreden. Verifieer de invoer alstublieft.
- The primary goals of this format is to allow a simple XML format
- that is mostly human readable. The generation and parsing of the
- various data types are done through the TypeConverter classes
- associated with the data types.
+Fout:
+{0}
+
+
+ Fout opgetreden
+
+
+ OnNodeRenamed moet zijn geïmplementeerd in de afgeleide klasse.
+
+
+ Structuurweergave mag niet leeg zijn.
+
+
+ Fout tijdens slepen/neerzetten: {0}.
+
+
+ Het geselecteerde element kan niet worden verwijderd.
+
+
+ De methode of operatie is niet geïmplementeerd.
+
+
+ Datumtijd notatie niet zoals verwacht.
+
+
+ Validatie van cel is mislukt: {0}.
+
+
+ Validatie van rij is mislukt: {0}.
+
+
+ Ongeldige rij: {0}.
+
+
+ Plakken waarden mislukt: {0}.
+
+
+ Ongeldig geplakte rij {0} wordt overgeslagen.
+
+
+ Kan de waarde in cel [{0}, {1}] niet plakken. Rij {0} wordt overgeslagen.
+
+
+ Kan niet plakken in een gefilterde tableview.
+
+
+ Kan niet plakken in gesorteerde kolom.
+
+
+ Er zijn geen waardes om te plakken (kopteksten worden overgeslagen).
+
+
+ Kan alleen in rechthoekige selectie plakken.
+
+
+ Klembord bevat geen tekst. Hierdoor kan het niet in de tabel worden geplakt.
+
+
+ Wilt u de waarde corrigeren?
- Example:
-
- ... ado.net/XML headers & schema ...
- text/microsoft-resx
- 1.3
- System.Resources.ResXResourceReader, System.Windows.Forms, ...
- System.Resources.ResXResourceWriter, System.Windows.Forms, ...
- this is my long string
- Blue
-
- [base64 mime encoded serialized .NET Framework object]
-
-
- [base64 mime encoded string representing a byte array form of the .NET Framework object]
-
-
- There are any number of "resheader" rows that contain simple
- name/value pairs.
-
- Each data row contains a name, and value. The row also contains a
- type or mimetype. Type corresponds to a .NET class that support
- text/value conversion through the TypeConverter architecture.
- Classes that don't support this are serialized and stored with the
- mimetype set.
-
- The mimetype is used for serialized objects, and tells the
- ResXResourceReader how to depersist the object. This is currently not
- extensible. For a given mimetype the value must be set accordingly:
-
- Note - application/x-microsoft.net.object.binary.base64 is the format
- that the ResXResourceWriter will generate, however the reader can
- read any of the formats listed below.
-
- mimetype: application/x-microsoft.net.object.binary.base64
- value : The object must be serialized with
- : System.Serialization.Formatters.Binary.BinaryFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.soap.base64
- value : The object must be serialized with
- : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.bytearray.base64
- value : The object must be serialized into a byte array
- : using a System.ComponentModel.TypeConverter
- : and then encoded with base64 encoding.
- -->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 1.3
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+Kies Ja om de waarde zelf te corrigeren. Kies Nee als u de oorspronkelijke waarde wilt terugkrijgen.
+
+
+ <aangepast>
+
+
+ Het is niet toegestaan om rijen aan deze tabel toe te voegen.
+
+
+ Niet in staat om cellen te selecteren wanneer tableView RowSelect ingeschakeld is. Gebruik in plaats daarvan SelectRow.
+
+
+ Kan tekenreeks {0} niet omzetten naar {1} om te plakken.
+
+
+ Kan waarde in cel [{0}, {1}] niet instellen. Reden: {2}.
+
+
+ Kan waarde voor rij {0} niet instellen. Reden: {1}.
+
+
+ Kopiëer alle kopteksten
+
+
+ Maak kolom los
+
+
+ Pin kolom vast
+
+
+ SelectionChanged event afgevuurd.
+
+
+ {0} exemplaren van {1} zijn met {2} vervangen.
+
+
+ Er is geen tekst om te zoeken.
+
+
+ Einde van document is bereikt.
+
+
+ Mijn Computer
+
+
+ Een optionele randstijl om te tekenen. Zet de waarde op 'Flat' om geen rand te tekenen.
+
+
+ Geen conversie van het type 'string' mogelijk.
+
+
+ Niet in staat om een presentatieobject te vinden voor niet geïnitialiseerd object.
+
+
+ Knoop moet opgegeven zijn om diens toestand op te kunnen nemen.
+
+
+ Knoop data moet aanwezig zijn om de toestand van diens knoop op te kunnen nemen.
+
+
+ Knoop heeft niet dezelfde data als de opgenomen knoop.
+
+
+ tot
+
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/Resources/CopyHS.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/DeleteHS1.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/PasteHS.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/binocular.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/computer.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/cross.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/csv-export.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/csv-import.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/down.bmp
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/down1.bmp
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/drive.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/edit-replace.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/edit_replace_all.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/folder.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/funnel--minus.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/funnel-small.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/information.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/page_white.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/pin.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/table_edit.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/tick.png
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/Resources/up.bmp
===================================================================
diff -u
Binary files differ
Index: Core/Common/src/Core.Common.Controls.Table/TableSelectionChangedEventArgs.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableSelectionChangedEventArgs.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableSelectionChangedEventArgs.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+
+namespace Core.Common.Controls.Table
+{
+ public class TableSelectionChangedEventArgs : EventArgs
+ {
+ ///
+ /// Selection Changed EventArgs
+ ///
+ public TableSelectionChangedEventArgs(IList cells)
+ {
+ Cells = cells;
+ }
+
+ public IList Cells { get; private set; }
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableView.Designer.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableView.Designer.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableView.Designer.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,93 @@
+namespace Core.Common.Controls.Table
+{
+ partial class TableView
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.dxGridControl = new DevExpress.XtraGrid.GridControl();
+ this.dxGridView = new DevExpress.XtraGrid.Views.Grid.GridView();
+ this.repositoryItemTimeEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemTimeEdit();
+ ((System.ComponentModel.ISupportInitialize)(this.dxGridControl)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.dxGridView)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.repositoryItemTimeEdit1)).BeginInit();
+ this.SuspendLayout();
+ //
+ // dxGridControl
+ //
+ this.dxGridControl.AllowRestoreSelectionAndFocusedRow = DevExpress.Utils.DefaultBoolean.True;
+ this.dxGridControl.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.dxGridControl.Location = new System.Drawing.Point(0, 0);
+ this.dxGridControl.LookAndFeel.SkinName = "Blue";
+ this.dxGridControl.LookAndFeel.Style = DevExpress.LookAndFeel.LookAndFeelStyle.Office2003;
+ this.dxGridControl.LookAndFeel.UseDefaultLookAndFeel = false;
+ this.dxGridControl.MainView = this.dxGridView;
+ this.dxGridControl.Name = "dxGridControl";
+ this.dxGridControl.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] {
+ this.repositoryItemTimeEdit1});
+ this.dxGridControl.Size = new System.Drawing.Size(564, 408);
+ this.dxGridControl.TabIndex = 3;
+ this.dxGridControl.UseEmbeddedNavigator = true;
+ this.dxGridControl.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] {
+ this.dxGridView});
+ //
+ // dxGridView
+ //
+ this.dxGridView.GridControl = this.dxGridControl;
+ this.dxGridView.Name = "dxGridView";
+ this.dxGridView.OptionsCustomization.AllowColumnMoving = false;
+ this.dxGridView.OptionsCustomization.AllowGroup = false;
+ this.dxGridView.OptionsDetail.EnableDetailToolTip = true;
+ this.dxGridView.OptionsSelection.MultiSelect = true;
+ this.dxGridView.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CellSelect;
+ this.dxGridView.OptionsView.ColumnAutoWidth = false;
+ this.dxGridView.OptionsView.NewItemRowPosition = DevExpress.XtraGrid.Views.Grid.NewItemRowPosition.Bottom;
+ this.dxGridView.OptionsView.ShowFooter = true;
+ this.dxGridView.OptionsView.ShowGroupPanel = false;
+ this.dxGridView.PaintStyleName = "Flat";
+ //
+ // repositoryItemTimeEdit1
+ //
+ this.repositoryItemTimeEdit1.AutoHeight = false;
+ this.repositoryItemTimeEdit1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] {
+ new DevExpress.XtraEditors.Controls.EditorButton()});
+ this.repositoryItemTimeEdit1.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss";
+ this.repositoryItemTimeEdit1.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom;
+ this.repositoryItemTimeEdit1.EditFormat.FormatString = "yyyy-MM-dd HH:mm:ss";
+ this.repositoryItemTimeEdit1.EditFormat.FormatType = DevExpress.Utils.FormatType.Custom;
+ this.repositoryItemTimeEdit1.EditValueChangedFiringMode = DevExpress.XtraEditors.Controls.EditValueChangedFiringMode.Default;
+ this.repositoryItemTimeEdit1.Mask.EditMask = "yyyy-MM-dd HH:mm:ss";
+ this.repositoryItemTimeEdit1.Name = "repositoryItemTimeEdit1";
+ this.repositoryItemTimeEdit1.ValidateOnEnterKey = true;
+ //
+ // TableView
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.dxGridControl);
+ this.Name = "TableView";
+ this.Size = new System.Drawing.Size(564, 408);
+ ((System.ComponentModel.ISupportInitialize)(this.dxGridControl)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.dxGridView)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.repositoryItemTimeEdit1)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private DevExpress.XtraEditors.Repository.RepositoryItemTimeEdit repositoryItemTimeEdit1;
+ private DevExpress.XtraGrid.GridControl dxGridControl;
+ private DevExpress.XtraGrid.Views.Grid.GridView dxGridView;
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableView.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableView.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableView.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,2521 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using Core.Common.Controls.Table.Properties;
+using Core.Common.Controls.Table.Editors;
+using Core.Common.Controls.Table.Validation;
+using Core.Common.Controls.Views;
+using Core.Common.Utils.Events;
+using Core.Common.Utils.Extensions;
+using Core.Common.Utils.Reflection;
+using DevExpress.Data;
+using DevExpress.Utils;
+using DevExpress.Utils.Drawing;
+using DevExpress.Utils.Menu;
+using DevExpress.XtraEditors;
+using DevExpress.XtraEditors.Repository;
+using DevExpress.XtraEditors.ViewInfo;
+using DevExpress.XtraGrid;
+using DevExpress.XtraGrid.Columns;
+using DevExpress.XtraGrid.Localization;
+using DevExpress.XtraGrid.Views.Base;
+using DevExpress.XtraGrid.Views.Grid;
+using DevExpress.XtraGrid.Views.Grid.ViewInfo;
+using log4net;
+using TypeConverter = Core.Common.Utils.TypeConverter;
+
+namespace Core.Common.Controls.Table
+{
+ ///
+ /// Graphical representation of tabular data.
+ ///
+ public partial class TableView : UserControl, IView, ISupportInitialize
+ {
+ public enum ValidationExceptionMode
+ {
+ Ignore,
+ NoAction,
+ DisplayError,
+ ThrowException
+ }
+
+ private static readonly ILog Log = LogManager.GetLogger(typeof(TableView));
+ private readonly ICollection selectedCells;
+ private readonly TableViewValidator tableViewValidator;
+ private readonly List columns;
+ private bool isPasting;
+ private bool isSelectionChanging;
+ private bool updatingSelection;
+ private bool showRowNumbers;
+ private bool autoGenerateColumns;
+ private bool refreshRequired;
+ private bool allowColumnSorting = true;
+ private bool f2Pressed;
+ private Timer refreshTimer;
+ private BindingSource bindingSource;
+ private GridCell[] cellsToFill;
+
+ public TableView()
+ {
+ InitializeComponent();
+
+ columns = new List();
+ ColumnMenuItems = new List();
+ selectedCells = new HashSet();
+ tableViewValidator = new TableViewValidator(this);
+ PasteController = new TableViewPasteController(this)
+ {
+ PasteBehaviour = TableViewPasteBehaviourOptions.SkipCellWhenValueIsInvalid
+ };
+
+ AllowColumnPinning = true;
+ AllowDeleteRow = true;
+ AutoGenerateColumns = true;
+ MultipleCellEdit = true;
+ dxGridView.OptionsView.ShowFooter = false;
+ dxGridView.OptionsBehavior.CopyToClipboardWithColumnHeaders = false; //mimic behavior of 8.2
+ GridLocalizer.Active = new TableViewExceptionMessageController();
+
+ Text = Resources.TableView_TableView_new_Table;
+
+ ReadOnlyCellForeColor = Color.Black; //just use black as a default to increase readability
+ ReadOnlyCellBackColor = Color.FromArgb(255, 244, 244, 244);
+ InvalidCellBackgroundColor = Color.Tomato;
+ ExceptionMode = ValidationExceptionMode.DisplayError;
+ ConfigureContextMenu();
+ SubscribeEvents();
+ CreateRefreshTimer();
+ }
+
+ public void ExportAsCsv(string fileName, string delimiter = ", ")
+ {
+ // the build-in export to file method depends on a devexpress dll we haven't included so far
+ using (var writer = new StreamWriter(fileName))
+ {
+ var visibleColumns = columns.Where(c => c.Visible).OrderBy(c => c.DisplayIndex);
+ var lastColumn = visibleColumns.Last();
+
+ foreach (var visibleColumn in visibleColumns)
+ {
+ writer.Write(visibleColumn.Caption);
+ if (visibleColumn != lastColumn)
+ {
+ writer.Write(delimiter);
+ }
+ }
+
+ writer.WriteLine();
+
+ var shownColumns = visibleColumns.Select(c => c.AbsoluteIndex).ToArray();
+
+ //writing the data
+ for (int x = 0; x < RowCount; x++)
+ {
+ for (int y = 0; y < shownColumns.Length; y++)
+ {
+ writer.Write(GetCellDisplayText(x, shownColumns[y]));
+ if (y != columns.Count - 1)
+ {
+ writer.Write(delimiter);
+ }
+ }
+ writer.WriteLine();
+ }
+ writer.Close();
+ }
+ }
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ UnSubscribeFromDataSource();
+
+ if (refreshTimer != null)
+ {
+ refreshTimer.Stop();
+ refreshTimer.Tick -= OnRefreshTimerOnTick;
+ refreshTimer.Dispose();
+ refreshTimer = null;
+ }
+
+ if (disposing)
+ {
+ //only dispose if disposing managed resource (otherwise called from other thread)
+ // prevents memory leaks
+ foreach (var view in dxGridControl.Views.Cast().ToList())
+ {
+ view.Dispose();
+ }
+ dxGridControl.Dispose();
+ }
+
+ if (columns != null)
+ {
+ foreach (var column in columns)
+ {
+ column.Dispose();
+ }
+ }
+
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+
+ try
+ {
+ /*
+ Localize bug in XtraEditors:
+
+ System.InvalidOperationException : Value Dispose() cannot be called while doing CreateHandle().
+ at System.Windows.Forms.Control.Dispose(Boolean disposing)
+ at DevExpress.XtraEditors.ScrollBarBase.Dispose(Boolean disposing)
+ at System.ComponentModel.Component.Dispose()
+ at DevExpress.XtraGrid.Scrolling.ScrollInfo.Dispose()
+ at DevExpress.XtraGrid.Views.Grid.GridView.Dispose(Boolean disposing)
+ at System.ComponentModel.Component.Dispose()
+ at DevExpress.XtraGrid.GridControl.RemoveView(BaseView gv, Boolean disposeView)
+ at DevExpress.XtraGrid.GridControl.RemoveView(BaseView gv)
+ at DevExpress.XtraGrid.GridControl.Dispose(Boolean disposing)
+ at System.ComponentModel.Component.Dispose()
+ at System.Windows.Forms.Control.Dispose(Boolean disposing)
+ at System.Windows.Forms.ContainerControl.Dispose(Boolean disposing)
+ at Core.Common.Controls.Swf.Table.TableView.Dispose(Boolean disposing) in TableView.Designer.cs: line 22
+ */
+ base.Dispose(disposing);
+ }
+ catch (InvalidOperationException e)
+ {
+ Log.Debug("Strange bug in XtraGrid control, from time to time crashes", e);
+ }
+ }
+
+ ///
+ /// Converts value pasted from clipboard, currently always a string, to a value of the type
+ /// required by the underlying datasource.
+ /// In addition to default conversion for e.g string to int by
+ /// TypeConverter.ConvertValueToTargetType
+ /// There is added support for the RepositoryItemImageComboBox where the description (will default be
+ /// copied to clipboard) will be converted to value.
+ /// - NB the base class RepositoryItemComboBox does not have items with value and description
+ ///
+ ///
+ ///
+ ///
+ internal object ConvertStringValueToDataValue(int columnIndex, string cellValue)
+ {
+ object value = null;
+ RepositoryItem editor = dxGridView.Columns[columnIndex].ColumnEdit;
+ Type columnType = dxGridView.Columns[columnIndex].ColumnType;
+ if (null != editor)
+ {
+ var imageComboBoxEditor = editor as RepositoryItemImageComboBox;
+ if (imageComboBoxEditor != null)
+ {
+ var repositoryItemImageComboBox = imageComboBoxEditor;
+ var map = new Dictionary();
+ for (int j = 0; j < repositoryItemImageComboBox.Items.Count; j++)
+ {
+ map[repositoryItemImageComboBox.Items[j].Description] =
+ repositoryItemImageComboBox.Items[j].Value;
+ }
+ if (map.ContainsKey(cellValue))
+ {
+ value = map[cellValue];
+ }
+ }
+ else if (editor is RepositoryItemComboBox || editor is RepositoryItemLookUpEdit)
+ {
+ var valueLookUp = new Dictionary();
+
+ var comboBoxEditor = editor as RepositoryItemComboBox;
+ if (comboBoxEditor != null)
+ {
+ var repositoryItemComboBox = comboBoxEditor;
+ valueLookUp = repositoryItemComboBox.Items.OfType().ToDictionary(i => i.DisplayText, i => i.Value);
+ }
+ else
+ {
+ var lookUpEdit = (RepositoryItemLookUpEdit) editor;
+ var comboBoxItems = lookUpEdit.DataSource as IEnumerable;
+ if (comboBoxItems != null)
+ {
+ valueLookUp = comboBoxItems.ToDictionary(i => i.DisplayText, i => i.Value);
+ }
+ }
+
+ if (valueLookUp.Any() && valueLookUp.ContainsKey(cellValue))
+ {
+ value = valueLookUp[cellValue];
+ }
+ else if (comboBoxEditor != null) // items are not mandatory
+ {
+ value = cellValue;
+ }
+ }
+ else
+ {
+ value = ConvertToColumnValue(cellValue, columnType);
+ }
+ }
+ else if (dxGridView.Columns[columnIndex].RealColumnEdit is RepositoryItemCheckEdit)
+ {
+ return cellValue == "Checked";
+ }
+ else
+ {
+ value = ConvertToColumnValue(cellValue, columnType);
+ }
+ return value;
+ }
+
+ private TableViewColumn GetColumnByDxColumn(GridColumn dxGridColumn)
+ {
+ return columns.FirstOrDefault(c => c.AbsoluteIndex == dxGridColumn.AbsoluteIndex);
+ }
+
+ private void BestFitColumnsWithOnlyFirstWordOfHeader()
+ {
+ var oldHeaders = columns.ToDictionary(c => c, c => c.Caption);
+
+ dxGridView.BeginUpdate();
+ try
+ {
+ foreach (var column in columns)
+ {
+ string caption = column.Caption;
+
+ //Say the caption is 'Discharge on Lateral (m3/s)'. We're trying to do
+ //something a bit smarter than just ignore the header entirely: we try
+ //to get the first word (eg: "Discharge"), add room for the ellipsis
+ //and keep that into view
+
+ if (!String.IsNullOrEmpty(caption))
+ {
+ var indexOfWhitespace = caption.IndexOfAny(new[]
+ {
+ ' ',
+ '\t'
+ });
+ if (indexOfWhitespace >= 0)
+ {
+ //add space for ellipsis
+ column.Caption = caption.Substring(0, indexOfWhitespace) + "...";
+ }
+ }
+ }
+
+ dxGridView.BestFitColumns();
+
+ //restore the original columns
+ foreach (var column in columns)
+ {
+ column.Caption = oldHeaders[column];
+ }
+ }
+ finally
+ {
+ dxGridView.EndUpdate();
+ }
+ }
+
+ private bool DeselectSelectCells(int top, int left, int bottom, int right)
+ {
+ var cellsDeselected = false;
+ // dxGridControl.SuspendLayout();
+ dxGridView.BeginSelection();
+ for (int y = top; y <= bottom; y++)
+ {
+ for (int x = left; x <= right; x++)
+ {
+ var selectedCell = selectedCells.FirstOrDefault(c => c.Column == GetColumnByDisplayIndex(x) && c.RowIndex == y);
+ if (selectedCell != null)
+ {
+ DeselectCell(selectedCell);
+ cellsDeselected = true;
+ }
+ }
+ }
+ dxGridView.EndSelection();
+ //dxGridControl.ResumeLayout();
+
+ return cellsDeselected;
+ }
+
+ private void AddEnumCellEditors()
+ {
+ foreach (var column in columns.Where(c => c.ColumnType.IsEnum && c.Editor == null))
+ {
+ column.Editor = new ComboBoxTypeEditor
+ {
+ Items = Enum.GetValues(column.ColumnType),
+ ItemsMandatory = false,
+ CustomFormatter = new EnumFormatter(column.ColumnType)
+ };
+ }
+ }
+
+ private static void CopyPasteControllerPasteFailed(object sender, EventArgs e)
+ {
+ MessageBox.Show(e.Value);
+ }
+
+ private void BindingListListChanged(object sender, ListChangedEventArgs e)
+ {
+ if (!AutoGenerateColumns || e.ListChangedType != ListChangedType.PropertyDescriptorChanged || e.PropertyDescriptor == null)
+ {
+ return;
+ }
+
+ // has column name changed
+ var column = dxGridView.Columns.ColumnByName(e.PropertyDescriptor.DisplayName);
+ if (column != null)
+ {
+ return;
+ }
+
+ column = dxGridView.Columns[e.NewIndex];
+
+ column.FieldName = e.PropertyDescriptor.Name;
+ column.Caption = e.PropertyDescriptor.DisplayName;
+ }
+
+ private void DataSourceDataTableColumnsCollectionChanged(object sender, CollectionChangeEventArgs e)
+ {
+ if (e.Action == CollectionChangeAction.Add || e.Action == CollectionChangeAction.Remove)
+ {
+ if (AutoGenerateColumns)
+ {
+ dxGridView.PopulateColumns();
+ BuildColumnWrappers();
+ BestFitColumns();
+ }
+ }
+ }
+
+ private void DataSourcePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ refreshRequired = true;
+ }
+
+ private void DataSourceCollectionChanged(object sender, NotifyCollectionChangeEventArgs e)
+ {
+ refreshRequired = true;
+ UpdateHeaderColumnSize();
+ }
+
+ ///
+ /// Checks if the mouse is clicked at the Header Panel Button in the grid.
+ /// If yes select entire grid (TOOLS-2834)
+ /// cfr: http://documentation.devexpress.com/#WindowsForms/CustomDocument532
+ /// "The header panel button belongs to both the column header panel and row
+ /// indicator panel elements. By default, the header panel button has no special
+ /// functionality. When the View is used to represent detail data, the header
+ /// panel button serves as a zoom button."
+ ///
+ ///
+ ///
+ private void HandleHeaderPanelButton(object sender, MouseEventArgs e)
+ {
+ var view = sender as GridView;
+ if (view == null)
+ {
+ return;
+ }
+ var hitInfo = view.CalcHitInfo(new Point(e.X, e.Y));
+ if ((hitInfo.HitTest == GridHitTest.ColumnButton) && (hitInfo.InColumn == false))
+ {
+ view.SelectAll();
+ }
+ }
+
+ private static DXMenuItem GetItemByStringId(DXPopupMenu menu, GridStringId id)
+ {
+ return menu.Items.Cast().FirstOrDefault(item => ((GridStringId) item.Tag) == id);
+ }
+
+ private void SubscribeToDataSource()
+ {
+ if (dxGridControl.DataSource == null)
+ {
+ return;
+ }
+
+ var propertyChanged = dxGridControl.DataSource as INotifyPropertyChanged;
+ if (propertyChanged != null)
+ {
+ propertyChanged.PropertyChanged += DataSourcePropertyChanged;
+ }
+
+ var collectionChanged = dxGridControl.DataSource as INotifyCollectionChanged;
+ if (collectionChanged != null)
+ {
+ collectionChanged.CollectionChanged += DataSourceCollectionChanged;
+ }
+
+ var dataTable = dxGridControl.DataSource as DataTable;
+ if (dataTable != null)
+ {
+ var table = dataTable;
+ table.Columns.CollectionChanged += DataSourceDataTableColumnsCollectionChanged;
+ }
+
+ var bindingList = dxGridControl.DataSource as IBindingList;
+ if (bindingList != null)
+ {
+ bindingList.ListChanged += BindingListListChanged;
+ }
+ }
+
+ private void UnSubscribeFromDataSource()
+ {
+ if (dxGridControl == null || dxGridControl.DataSource == null)
+ {
+ return;
+ }
+
+ var propertyChanged = dxGridControl.DataSource as INotifyPropertyChanged;
+ if (propertyChanged != null)
+ {
+ propertyChanged.PropertyChanged -= DataSourcePropertyChanged;
+ }
+
+ var notifyCollectionChanged = dxGridControl.DataSource as INotifyCollectionChanged;
+ if (notifyCollectionChanged != null)
+ {
+ notifyCollectionChanged.CollectionChanged -= DataSourceCollectionChanged;
+ }
+
+ var dataTable = dxGridControl.DataSource as DataTable;
+ if (dataTable != null)
+ {
+ var table = dataTable;
+ table.Columns.CollectionChanged -= DataSourceDataTableColumnsCollectionChanged;
+ }
+
+ var bindingSource = dxGridControl.DataSource as BindingSource;
+ if (bindingSource != null)
+ {
+ bindingSource.ListChanged -= BindingListListChanged;
+ }
+ }
+
+ ///
+ /// Calculate width of the header column based on grid font
+ ///
+ private void UpdateHeaderColumnSize()
+ {
+ var indicatorWidth = (int) dxGridControl.Font.SizeInPoints*RowCount.ToString(CultureInfo.InvariantCulture).Length + 15;
+ dxGridView.IndicatorWidth = showRowNumbers ? indicatorWidth : -1;
+ Refresh();
+ }
+
+ ///
+ /// Returns true if the whole selection is readonly. This can be on cell,column or table level If a cell is not it returns false.
+ ///
+ ///
+ private bool GetSelectionIsReadonly()
+ {
+ //no selection use tableview readonly
+ if (selectedCells.Count == 0)
+ {
+ return ReadOnly;
+ }
+
+ //A selection is readonly if ALL cells are readonly (otherwise i can change the not readonly part)
+ return selectedCells.All(cell => CellIsReadOnly(cell.RowIndex, cell.Column));
+ }
+
+ private void UpdateSelectionFromGridControl()
+ {
+ if (updatingSelection)
+ {
+ return;
+ }
+
+ updatingSelection = true;
+
+ ClearSelectedCells();
+
+ var gridViewSelectedCells = dxGridView.GetSelectedCells();
+ foreach (var cell in gridViewSelectedCells)
+ {
+ var tableViewCell = new TableViewCell(cell.RowHandle, GetColumnByDxColumn(cell.Column));
+ SelectCell(tableViewCell);
+ }
+
+ if (!IsEditing && !isPasting)
+ {
+ if (SelectionChanged != null)
+ {
+ Log.DebugFormat(Resources.TableView_UpdateSelectionFromGridControl_Firing_selection_changed_event);
+ SelectionChanged(this, new TableSelectionChangedEventArgs(selectedCells.ToArray()));
+ }
+ }
+
+ // Update the row context menu
+ RowContextMenu.Items.OfType().ForEachElementDo(mi => mi.Available = true);
+ RowContextMenu.Items.OfType()
+ .Where(mi => mi.Name == "btnDelete" || mi.Name == "btnPaste")
+ .ForEachElementDo(mi => mi.Available = !GetSelectionIsReadonly());
+
+ updatingSelection = false;
+ }
+
+ private void BuildColumnWrappers()
+ {
+ if (!AutoGenerateColumns)
+ {
+ return;
+ }
+
+ columns.Clear();
+
+ foreach (GridColumn dxColumn in dxGridView.Columns)
+ {
+ columns.Add(new TableViewColumn(dxGridView, dxGridControl, dxColumn, this, false)
+ {
+ SortingAllowed = AllowColumnSorting
+ });
+ }
+ }
+
+ private void ShowEditorIfRowSelect()
+ {
+ if (dxGridView.FocusedColumn != null && (RowSelect) && (dxGridView.ActiveEditor == null))
+ {
+ dxGridView.ShowEditor();
+ }
+ }
+
+ private GridColumn GetDxColumnByDisplayIndex(int displayIndex)
+ {
+ return dxGridView.Columns[columns.First(c => c.DisplayIndex == displayIndex).AbsoluteIndex];
+ }
+
+ private void UpdateColumnHeaderMenu(GridMenuEventArgs e, TableViewColumn viewColumn)
+ {
+ //show grid menu is handled to remove menu-items. For grouping etc.
+ //No way to do this in a setting :(
+ //see http://community.devexpress.com/forums/t/61316.aspx
+
+ var ids = new[]
+ {
+ GridStringId.MenuColumnGroupBox,
+ GridStringId.MenuColumnGroup,
+ GridStringId.MenuColumnRemoveColumn
+ };
+
+ var dxMenuItems = ids.Select(id => GetItemByStringId(e.Menu, id));
+ var dxMenuItemsToHide = dxMenuItems.Where(item => item != null);
+ foreach (var item in dxMenuItemsToHide)
+ {
+ item.Visible = false;
+ }
+
+ if (AllowColumnPinning && viewColumn != null)
+ {
+ var pinColumnMenuItem = new DXMenuCheckItem
+ {
+ Caption = viewColumn.Pinned ? Resources.TableView_UpdateColumnHeaderMenu_Unpin_Column : Resources.TableView_UpdateColumnHeaderMenu_Pin_Column,
+ Checked = viewColumn.Pinned,
+ Image = Resources.pin
+ };
+
+ pinColumnMenuItem.CheckedChanged += (sender, args) => { viewColumn.Pinned = pinColumnMenuItem.Checked; };
+
+ e.Menu.Items.Add(pinColumnMenuItem);
+ }
+
+ var copyHeadersColumnMenuItem = new DXMenuItem
+ {
+ Caption = Resources.TableView_UpdateColumnHeaderMenu_Copy_all_headers,
+ Image = Resources.CopyHS
+ };
+
+ copyHeadersColumnMenuItem.Click += (sender, args) =>
+ {
+ var sb = new StringBuilder();
+
+ CopyHeader(sb);
+
+ Clipboard.Clear();
+ Clipboard.SetData(DataFormats.Text, sb.ToString());
+ };
+
+ e.Menu.Items.Add(copyHeadersColumnMenuItem);
+ }
+
+ private bool ValidateAndCommitRow(int rowIndex)
+ {
+ string errorText;
+ if (!tableViewValidator.ValidateRow(rowIndex, out errorText))
+ {
+ Log.ErrorFormat(Resources.TableView_ValidateAndCommitRow_Can_not_set_value_for_row_0_reason_1_, rowIndex, errorText);
+ dxGridView.CancelUpdateCurrentRow();
+ tableViewValidator.RefreshRowData();
+ dxGridView.DeleteRow(rowIndex);
+ return false;
+ }
+
+ dxGridView.FocusedRowHandle = rowIndex;
+ //this line is needed for the changes to be 'commited' and the row
+ //to leave an updating state. http://community.devexpress.com/forums/p/30892/106718.aspx
+ //unfortunately hard to write a test without exposing/hacking too much
+ dxGridView.UpdateCurrentRow();
+ tableViewValidator.RefreshRowData();
+ return true;
+ }
+
+ private bool SetCellValueInternal(int rowIndex, int columnDisplayIndex, object value)
+ {
+ var col = GetDxColumnByDisplayIndex(columnDisplayIndex);
+
+ if (CellIsReadOnly(rowIndex, GetColumnByDxColumn(col)))
+ {
+ return false;
+ }
+
+ //check if the value can be converted to the column type
+ object objectValue = value is string
+ ? ConvertStringValueToDataValue(col.AbsoluteIndex, (string) value)
+ : value;
+ if (objectValue == null)
+ {
+ Log.ErrorFormat(Resources.TableView_SetCellValueInternal_Can_not_set_value_into_cell_0_1_reason_2_, rowIndex, col.AbsoluteIndex, Resources.TableView_SetCellValueInternal_No_conversion_from_string_possible);
+ return false;
+ }
+
+ string error;
+ if (!tableViewValidator.ValidateCell(new TableViewCell(rowIndex, GetColumnByDxColumn(col)), objectValue, out error))
+ {
+ Log.ErrorFormat(Resources.TableView_SetCellValueInternal_Can_not_set_value_into_cell_0_1_reason_2_, rowIndex, col.AbsoluteIndex, error);
+ return false;
+ }
+
+ // (Gijs) We are mixing the row handlers and indices throughout this wrapper: should be fixed, as
+
+ dxGridView.FocusedRowHandle = rowIndex;
+
+ dxGridView.SetRowCellValue(rowIndex, col, objectValue);
+ return true;
+ }
+
+ private static object ConvertToColumnValue(string cellValue, Type columnType)
+ {
+ try
+ {
+ return TypeConverter.ConvertValueToTargetType(columnType, cellValue);
+ }
+ catch (Exception)
+ {
+ if (string.IsNullOrEmpty(cellValue.TrimStart()))
+ {
+ if (columnType.IsValueType)
+ {
+ return Activator.CreateInstance(columnType);
+ }
+ return null;
+ }
+
+ // still try to parse double or float numbers
+ if (columnType == typeof(double) || columnType == typeof(float))
+ {
+ double value;
+ if (double.TryParse(cellValue, out value))
+ {
+ return value;
+ }
+ }
+
+ Log.WarnFormat(Resources.TableView_ConvertToColumnValue_Unable_to_convert_string_0_to_1_for_paste, cellValue, columnType);
+ return null;
+ }
+ }
+
+ #region Public properties
+
+ ///
+ /// Specifies whether the edit buttons on the bottom of the table view is shown
+ ///
+ public bool EditButtons
+ {
+ get
+ {
+ return dxGridControl.UseEmbeddedNavigator;
+ }
+ set
+ {
+ dxGridControl.UseEmbeddedNavigator = value;
+ }
+ }
+
+ public bool AllowDeleteRow
+ {
+ get
+ {
+ if (bindingSource == null) // lazy initialize
+ {
+ bindingSource = new BindingSource
+ {
+ DataSource = dxGridView.DataSource
+ };
+ }
+
+ var tableAllowRemove = dxGridView.OptionsBehavior.AllowDeleteRows;
+ var dataAllowsRemove = bindingSource.AllowRemove;
+
+ // better code, but doesn't work for List (hacked through BindingSource):
+ // dataAllowsNew = xGridView.DataController != null && dxGridView.DataController.AllowNew;
+
+ return (tableAllowRemove == DefaultBoolean.True || tableAllowRemove == DefaultBoolean.Default) &&
+ dataAllowsRemove;
+ }
+ set
+ {
+ dxGridView.OptionsBehavior.AllowDeleteRows = value ? DefaultBoolean.True : DefaultBoolean.False;
+ if (dxGridControl.EmbeddedNavigator != null)
+ {
+ dxGridControl.EmbeddedNavigator.Buttons.Remove.Visible = value;
+ }
+ }
+ }
+
+ public bool AllowAddNewRow
+ {
+ get
+ {
+ if (bindingSource == null) // lazy initialize
+ {
+ bindingSource = new BindingSource
+ {
+ DataSource = dxGridView.DataSource
+ };
+ }
+
+ var tableAllowNew = dxGridView.OptionsBehavior.AllowAddRows;
+ var dataAllowsNew = bindingSource.AllowNew;
+
+ // better code, but doesn't work for List (hacked through BindingSource):
+ // dataAllowsNew = xGridView.DataController != null && dxGridView.DataController.AllowNew;
+
+ return (tableAllowNew == DefaultBoolean.True || tableAllowNew == DefaultBoolean.Default) &&
+ dataAllowsNew;
+ }
+ set
+ {
+ dxGridView.OptionsBehavior.AllowAddRows = value ? DefaultBoolean.True : DefaultBoolean.False;
+ dxGridView.OptionsView.NewItemRowPosition = value ? NewItemRowPosition.Bottom : NewItemRowPosition.None;
+ if (dxGridControl.EmbeddedNavigator != null)
+ {
+ dxGridControl.EmbeddedNavigator.Buttons.Append.Enabled = value;
+ }
+ }
+ }
+
+ public bool AllowColumnSorting
+ {
+ get
+ {
+ return allowColumnSorting;
+ }
+ set
+ {
+ if (allowColumnSorting == value)
+ {
+ return;
+ }
+
+ allowColumnSorting = value;
+ foreach (var column in columns)
+ {
+ column.SortingAllowed = allowColumnSorting;
+ }
+ }
+ }
+
+ public bool AllowColumnPinning { get; set; }
+
+ ///
+ /// Gets or sets whether multiple rows can be selected
+ ///
+ public bool MultiSelect
+ {
+ get
+ {
+ return dxGridView.OptionsSelection.MultiSelect;
+ }
+ set
+ {
+ dxGridView.OptionsSelection.MultiSelect = value;
+ }
+ }
+
+ public bool IncludeHeadersOnCopy { get; set; }
+
+ ///
+ /// Gets a boolean value indicating that the view is being edited or not
+ ///
+ [Browsable(false)]
+ public bool IsEditing
+ {
+ get
+ {
+ return dxGridView.IsEditing || dxGridView.FocusedRowModified;
+ }
+ }
+
+ ///
+ /// TODO: If RowSelect is true, dxGridView.GetSelectedCells etc will give an empty array.... SelectedRows will stiull work.
+ ///
+ public bool RowSelect
+ {
+ get
+ {
+ return dxGridView.OptionsSelection.MultiSelectMode == GridMultiSelectMode.RowSelect;
+ }
+ set
+ {
+ dxGridView.OptionsSelection.EnableAppearanceFocusedCell = false;
+ dxGridView.FocusRectStyle = DrawFocusRectStyle.None;
+ dxGridView.OptionsSelection.MultiSelectMode = (value) ? GridMultiSelectMode.RowSelect : GridMultiSelectMode.CellSelect;
+ }
+ }
+
+ public bool ShowRowNumbers
+ {
+ get
+ {
+ return showRowNumbers;
+ }
+ set
+ {
+ showRowNumbers = value;
+ UpdateHeaderColumnSize();
+ }
+ }
+
+ public bool ColumnAutoWidth
+ {
+ get
+ {
+ return dxGridView.OptionsView.ColumnAutoWidth;
+ }
+ set
+ {
+ dxGridView.OptionsView.ColumnAutoWidth = value;
+ }
+ }
+
+ public bool UseCenteredHeaderText
+ {
+ get
+ {
+ return dxGridView.Appearance.HeaderPanel.TextOptions.HAlignment == HorzAlignment.Center;
+ }
+ set
+ {
+ dxGridView.Appearance.HeaderPanel.TextOptions.HAlignment = (value)
+ ? HorzAlignment.Center
+ : HorzAlignment.Default;
+ }
+ }
+
+ public bool ReadOnly
+ {
+ get
+ {
+ return !dxGridView.Editable;
+ }
+ set
+ {
+ dxGridView.OptionsBehavior.Editable = !value;
+ }
+ }
+
+ public bool MultipleCellEdit { get; set; }
+
+ ///
+ /// Determines whether the tableview generates columns when
+ /// setting data
+ ///
+ public bool AutoGenerateColumns
+ {
+ get
+ {
+ return autoGenerateColumns;
+ }
+ set
+ {
+ autoGenerateColumns = value;
+ //update gridview behavior
+ dxGridView.OptionsBehavior.AutoPopulateColumns = value;
+ }
+ }
+
+ public bool AutoSizeRows
+ {
+ get
+ {
+ return dxGridView.OptionsView.RowAutoHeight;
+ }
+ set
+ {
+ dxGridView.OptionsView.RowAutoHeight = value;
+ }
+ }
+
+ public int HeaderHeigth
+ {
+ get
+ {
+ return dxGridView.ColumnPanelRowHeight;
+ }
+ set
+ {
+ if (value > 0)
+ {
+ dxGridView.Appearance.HeaderPanel.TextOptions.WordWrap = WordWrap.Wrap;
+ }
+ dxGridView.ColumnPanelRowHeight = value;
+ }
+ }
+
+ public int RowHeight
+ {
+ get
+ {
+ return dxGridView.RowHeight;
+ }
+ set
+ {
+ dxGridView.RowHeight = value;
+ }
+ }
+
+ ///
+ /// Number of rows in the grid excluding the newrow and filtered rows.
+ ///
+ [Browsable(false)]
+ public int RowCount
+ {
+ get
+ {
+ return dxGridView.DataController.VisibleCount;
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public int FocusedRowIndex
+ {
+ get
+ {
+ return dxGridView.FocusedRowHandle;
+ }
+ set
+ {
+ if (dxGridView.FocusedRowHandle != value && dxGridView.FocusedRowHandle != int.MinValue && value > -1)
+ {
+ dxGridView.FocusedRowHandle = value;
+ }
+ }
+ }
+
+ [Browsable(false)]
+ public int[] SelectedRowsIndices
+ {
+ get
+ {
+ return dxGridView.GetSelectedRows();
+ }
+ }
+
+ [Browsable(false)]
+ public int[] SelectedColumnsIndices
+ {
+ get
+ {
+ return selectedCells.Select(c => c.Column.AbsoluteIndex).OrderBy(i => i).Distinct().ToArray();
+ }
+ }
+
+ ///
+ /// Gets or sets the disabled cell fore color
+ ///
+ public Color ReadOnlyCellForeColor { get; set; }
+
+ ///
+ /// Gets or sets the disabled cell fore color
+ ///
+ public Color ReadOnlyCellBackColor { get; set; }
+
+ ///
+ /// Gets or sets the background color of the invalid cell (value)
+ ///
+ public Color InvalidCellBackgroundColor { get; set; }
+
+ ///
+ /// Returns the focused row (also works if the focused row is new or deleted)
+ ///
+ [Browsable(false)]
+ public object CurrentFocusedRowObject
+ {
+ get
+ {
+ return dxGridView.GetFocusedRow();
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public object Data
+ {
+ get
+ {
+ return dxGridControl.DataSource;
+ }
+ set
+ {
+ dxGridView.CancelUpdateCurrentRow();
+ UnSubscribeFromDataSource();
+ bindingSource = null;
+ ClearSelection();
+
+ // clear before binding enables rebinding to new function; will remove old columns
+ if (dxGridControl.DataSource != value)
+ {
+ // do not explicitly clear columns; this will also remove user added column editors
+
+ dxGridControl.DataSource = value;
+
+ if (AutoGenerateColumns)
+ {
+ dxGridView.PopulateColumns();
+ }
+ }
+
+ if (value == null)
+ {
+ return;
+ }
+
+ SubscribeToDataSource();
+
+ BeginInit();
+
+ BuildColumnWrappers();
+ AddEnumCellEditors();
+ UpdateHeaderColumnSize();
+
+ EndInit();
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public TableViewPasteController PasteController { get; set; }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public ValidationExceptionMode ExceptionMode { get; set; }
+
+ [Browsable(false)]
+ public IEnumerable SelectedCells
+ {
+ get
+ {
+ return selectedCells;
+ }
+ }
+
+ // avoid serialization of Columns into resx files,
+ // when something changes in columns designers becomes mad because of broken resx files
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public ReadOnlyCollection Columns
+ {
+ get
+ {
+ return columns.AsReadOnly();
+ }
+ }
+
+ public override ContextMenuStrip ContextMenuStrip
+ {
+ get
+ {
+ return RowContextMenu;
+ }
+ set
+ {
+ RowContextMenu = value;
+ }
+ }
+
+ public ContextMenuStrip RowContextMenu
+ {
+ get
+ {
+ return dxGridControl.ContextMenuStrip;
+ }
+ private set
+ {
+ dxGridControl.ContextMenuStrip = value;
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public IList ColumnMenuItems { get; set; }
+
+ ///
+ /// Gets or sets the filter to evaluate if the value of the cell is invalid
+ ///
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Func InvalidCellFilter { get; set; }
+
+ ///
+ /// Gets or sets the filter that can be used for making cells read-only
+ ///
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Func ReadOnlyCellFilter { get; set; }
+
+ ///
+ /// Gets or sets the filter that can be used for styling a cell
+ ///
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Func DisplayCellFilter { get; set; }
+
+ ///
+ /// Function for getting or setting unbound column values
+ /// Parameters : column index, datasource row index, is getter, is setter, value
+ ///
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Func UnboundColumnData { get; set; }
+
+ ///
+ /// Gets or sets the row values validator. The validator should return a RowValidationResult
+ ///
+ /// ?Does not validate before commit to data source?
+ [Browsable(false)]
+ public Func RowValidator { get; set; }
+
+ ///
+ /// Gets or sets the cell value editor validator. The validator should return true on valid values
+ ///
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Func> InputValidator { get; set; }
+
+ ///
+ /// Gets or sets the function that checks if the current selection can be deleted.
+ /// When null or returning true, deletion is allowed.
+ ///
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Func CanDeleteCurrentSelection { get; set; }
+
+ ///
+ /// Gets or sets the function for deleting selected rows (return value indicates if the deleting is handled)
+ /// When null or returning false the default delete will be executed
+ ///
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Func RowDeleteHandler { get; set; }
+
+ public bool IsEndEditOnEnterKey { get; set; }
+
+ ///
+ /// Enable filtering for all columns
+ ///
+ public bool AllowColumnFiltering
+ {
+ get
+ {
+ return columns.OfType().Any(c => c.FilteringAllowed);
+ }
+ set
+ {
+ foreach (var column in columns.OfType())
+ {
+ column.FilteringAllowed = value;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Public functions
+
+ public new void ResetBindings()
+ {
+ dxGridControl.ResetBindings();
+ if (AutoGenerateColumns)
+ {
+ dxGridView.PopulateColumns();
+ BuildColumnWrappers();
+ BestFitColumns();
+ }
+
+ base.ResetBindings();
+ }
+
+ ///
+ /// Function to check if the current focused row is a
+ /// new row (row that's not committed to the datasource)
+ ///
+ /// If the focused row is a new row
+ public bool OnNewRow()
+ {
+ return dxGridView.FocusedRowHandle.Equals(GridControl.NewItemRowHandle);
+ }
+
+ ///
+ /// Clear selected rows
+ ///
+ public void ClearSelection()
+ {
+ dxGridView.ClearSelection();
+ }
+
+ ///
+ /// Allows to fit all columns to their contents.
+ ///
+ public void BestFitColumns(bool useOnlyFirstWordOfHeader = false)
+ {
+ dxGridView.BestFitMaxRowCount = columns.Count > 50 ? 10 : 50;
+
+ if (useOnlyFirstWordOfHeader)
+ {
+ BestFitColumnsWithOnlyFirstWordOfHeader();
+ }
+ else
+ {
+ dxGridView.BestFitColumns();
+ }
+ }
+
+ public int GetRowIndexByDataSourceIndex(int datarowIndex)
+ {
+ return dxGridView.GetRowHandle(datarowIndex);
+ }
+
+ ///
+ /// Sets a display filter on a column. Note that it filters values on it's display text rather than the actual value.
+ ///
+ /// The name of the column to apply a display filter to
+ /// The SQL-like filter expression to apply
+ public void SetColumnFilter(string columnName, string filter)
+ {
+ if (filter == string.Empty)
+ {
+ // Remove the filter rather than add or change it
+ dxGridView.ActiveFilter.Remove(dxGridView.Columns[columnName]);
+ return;
+ }
+ var columnFilterInfo = new ColumnFilterInfo(filter);
+ dxGridView.ActiveFilter.Add(dxGridView.Columns[columnName], columnFilterInfo);
+ }
+
+ public void BeginInit()
+ {
+ dxGridView.BeginUpdate();
+ dxGridControl.BeginUpdate();
+ }
+
+ public void EndInit()
+ {
+ dxGridControl.EndUpdate();
+ dxGridView.EndUpdate();
+ }
+
+ public TableViewColumn GetColumnByName(string columnName)
+ {
+ return columns.FirstOrDefault(c => c.Name == columnName);
+ }
+
+ public void SelectRow(int index, bool clearPreviousSelection = true)
+ {
+ SelectRows(new[]
+ {
+ index
+ }, clearPreviousSelection);
+ }
+
+ public void SelectRows(int[] indices, bool clearPreviousSelection = true)
+ {
+ dxGridView.BeginSelection();
+
+ if (clearPreviousSelection)
+ {
+ dxGridView.ClearSelection(); //clear any previous selection
+ }
+
+ dxGridView.HideEditor(); //close any open editor
+
+ for (int i = 0; i < indices.Length; i++)
+ {
+ if (i == 0)
+ {
+ dxGridView.SelectionChanged -= DxGridViewSelectionChanged;
+ }
+
+ if (i == indices.Length - 1)
+ {
+ dxGridView.SelectionChanged += DxGridViewSelectionChanged;
+ }
+
+ dxGridView.SelectRow(indices[i]);
+ }
+ dxGridView.EndSelection();
+ }
+
+ ///
+ /// Returns the index of the data source record which the specified row handle corresponds to.
+ ///
+ /// The visualized, zero-based row-index in the table
+ ///
+ /// An integer value representing the zero-based index of the data record to which the specified row handle corresponds
+ ///
+ public int GetDataSourceIndexByRowIndex(int rowIndex)
+ {
+ RefreshIfRequired();
+ return dxGridView.GetDataSourceRowIndex(rowIndex);
+ }
+
+ private void RefreshIfRequired()
+ {
+ if (refreshRequired)
+ {
+ RefreshData();
+ refreshRequired = false;
+ }
+ }
+
+ public void RefreshData()
+ {
+ dxGridControl.RefreshDataSource();
+ dxGridView.LayoutChanged();
+ }
+
+ public void ScheduleRefresh()
+ {
+ refreshRequired = true;
+ }
+
+ public bool CellIsReadOnly(int rowHandle, TableViewColumn column)
+ {
+ // Tableview readonly?
+ if (ReadOnly)
+ {
+ return true;
+ }
+
+ // Column does not exist or cannot be found (not visible for example)
+ if (column == null)
+ {
+ return true;
+ }
+
+ // Column readonly?
+ if (column.ReadOnly)
+ {
+ return true;
+ }
+
+ // Cell readonly?
+ if (ReadOnlyCellFilter != null)
+ {
+ return ReadOnlyCellFilter(new TableViewCell(rowHandle, column));
+ }
+
+ // Cell is not read only
+ return false;
+ }
+
+ ///
+ /// Assign a certain value to cell.
+ ///
+ /// Display index of the row
+ /// Display index of the column
+ /// String value to be set
+ public bool SetCellValue(int rowIndex, int columnIndex, object value)
+ {
+ tableViewValidator.AutoValidation = false;
+
+ try
+ {
+ if (!SetCellValueInternal(rowIndex, columnIndex, value))
+ {
+ return false;
+ }
+
+ if (!ValidateAndCommitRow(rowIndex))
+ {
+ return false;
+ }
+ }
+ finally
+ {
+ tableViewValidator.AutoValidation = true;
+ }
+
+ return true;
+ }
+
+ public bool SetRowCellValues(int rowIndex, int columnDisplayStartIndex, object[] cellValues)
+ {
+ tableViewValidator.AutoValidation = false;
+ var success = true;
+
+ try
+ {
+ for (int i = 0; i < cellValues.Length; i++)
+ {
+ if (CellIsReadOnly(rowIndex, GetColumnByDisplayIndex(i + columnDisplayStartIndex))) // skip readonly cells, does not affect success.
+ {
+ continue;
+ }
+ success &= SetCellValueInternal(rowIndex, i + columnDisplayStartIndex, cellValues[i]);
+ }
+
+ if (!success)
+ {
+ return false;
+ }
+
+ success = ValidateAndCommitRow(rowIndex);
+ }
+ finally
+ {
+ tableViewValidator.AutoValidation = true;
+ }
+
+ return success;
+ }
+
+ public object GetRowObjectAt(int rowIndex)
+ {
+ return dxGridView.RowCount > rowIndex && rowIndex >= 0 ? dxGridView.GetRow(rowIndex) : null;
+ }
+
+ ///
+ /// Gets value of a certain cell.
+ ///
+ /// Index of the row
+ /// Absolute index of the column
+ public object GetCellValue(int rowIndex, int absoluteColumnIndex)
+ {
+ return dxGridView.GetRowCellValue(rowIndex, dxGridView.Columns[absoluteColumnIndex]);
+ }
+
+ ///
+ /// Gets value of a certain cell.
+ ///
+ public object GetCellValue(TableViewCell cell)
+ {
+ return GetCellValue(cell.RowIndex, cell.Column.AbsoluteIndex);
+ }
+
+ ///
+ /// Selects cells in a square described by top,left -> bottom,right
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void SelectCells(int top, int left, int bottom, int right, bool clearOldSelection = true)
+ {
+ // dxGridControl.SuspendLayout();
+ dxGridView.BeginSelection();
+ if (RowSelect)
+ {
+ throw new InvalidOperationException(Resources.TableView_SelectCells_Unable_to_select_cells_when_tableView_has_RowSelect_enabled_Use_SelectRow_instead);
+ }
+
+ if (clearOldSelection)
+ {
+ ClearSelectedCells();
+ }
+
+ for (int y = top; y <= bottom; y++)
+ {
+ for (int x = left; x <= right; x++)
+ {
+ var tableViewCell = new TableViewCell(y, GetColumnByDisplayIndex(x));
+ SelectCell(tableViewCell);
+ }
+ }
+ dxGridView.EndSelection();
+ //dxGridControl.ResumeLayout();
+ }
+
+ private void SelectCell(TableViewCell cell)
+ {
+ if (!updatingSelection)
+ {
+ selectedCells.Add(cell);
+ var gridColumn = GetDxColumnByDisplayIndex(cell.Column.DisplayIndex);
+ dxGridView.SelectCell(cell.RowIndex, gridColumn);
+ }
+ }
+
+ private void ClearSelectedCells()
+ {
+ foreach (var cell in selectedCells.ToArray())
+ {
+ DeselectCell(cell);
+ }
+ }
+
+ private void DeselectCell(TableViewCell cell)
+ {
+ if (!updatingSelection && selectedCells.Remove(cell))
+ {
+ var gridColumn = GetDxColumnByDisplayIndex(cell.Column.DisplayIndex);
+ dxGridView.UnselectCell(cell.RowIndex, gridColumn);
+ }
+ }
+
+ ///
+ /// Pastes clipboard contens into current selection
+ ///
+ public void PasteClipboardContents()
+ {
+ isPasting = true;
+ PasteController.PasteClipboardContents();
+ isPasting = false;
+ }
+
+ ///
+ /// Copy original (not the display) values to the clipboard as strings
+ ///
+ public void CopySelectionToClipboard()
+ {
+ var sb = new StringBuilder();
+ var areAllCellsSelected = dxGridView.GetSelectedCells().Length == (dxGridView.DataRowCount*dxGridView.VisibleColumns.Count);
+
+ if (areAllCellsSelected && IncludeHeadersOnCopy)
+ {
+ CopyHeader(sb);
+ }
+
+ var selectedGridCells = dxGridView.GetSelectedCells();
+ var rowIndex = -1;
+ foreach (var cell in selectedGridCells)
+ {
+ if (rowIndex != cell.RowHandle)
+ {
+ if (rowIndex != -1)
+ {
+ sb.AppendLine();
+ }
+ rowIndex = cell.RowHandle;
+ }
+ else
+ {
+ sb.Append("\t");
+ }
+
+ sb.Append(dxGridView.GetRowCellValue(cell.RowHandle, cell.Column));
+ }
+
+ if (rowIndex != -1)
+ {
+ sb.AppendLine();
+ }
+
+ Clipboard.Clear();
+ Clipboard.SetData(DataFormats.Text, sb.ToString());
+ }
+
+ private void CopyHeader(StringBuilder sb)
+ {
+ var header = "";
+
+ for (var i = 0; i < dxGridView.Columns.Count; i++)
+ {
+ if (header != "")
+ {
+ header += "\t";
+ }
+
+ header += dxGridView.Columns[i].GetTextCaption().Replace("\n", " ");
+ }
+
+ sb.AppendLine(header);
+ }
+
+ public void SetFocus(int rowIndex, int columnIndex)
+ {
+ var column = GetDxColumnByDisplayIndex(columnIndex);
+
+ dxGridView.FocusedRowHandle = rowIndex;
+ dxGridView.FocusedColumn = column;
+
+ //this is needed to get the focus visible
+ dxGridView.ShowEditor();
+ dxGridView.HideEditor();
+ }
+
+ public void DeleteCurrentSelection()
+ {
+ if (ReadOnly)
+ {
+ return;
+ }
+
+ dxGridView.CancelUpdateCurrentRow(); // cancel any open changes (as that may trigger validation)
+
+ // Nothing to delete?
+ if (dxGridView.GetSelectedRows().Length == 0)
+ {
+ return;
+ }
+
+ // Is deletion allowed?
+ if (CanDeleteCurrentSelection != null && !CanDeleteCurrentSelection())
+ {
+ return;
+ }
+
+ //delete rows in case entire rows are selected
+ var groupBy = selectedCells.GroupBy(c => c.RowIndex);
+ var count = columns.Count(c => c.Visible);
+ if (AllowDeleteRow && (RowSelect || groupBy.All(g => g.Count() == count)))
+ {
+ if (RowDeleteHandler == null || !RowDeleteHandler())
+ {
+ dxGridView.DeleteSelectedRows();
+ }
+ return;
+ }
+
+ var selectedGridCells = selectedCells.ToList();
+ foreach (var c in selectedGridCells)
+ {
+ var defaultValue = c.Column.DefaultValue ??
+ TypeUtils.GetDefaultValue(c.Column.ColumnType);
+
+ SetCellValue(c.RowIndex, c.Column.DisplayIndex, Convert.ToString(defaultValue));
+ }
+ }
+
+ public void AddColumn(string dataSourcePropertyName, string columnCaption, bool readOnly = false, int width = 100, Type columnType = null, string displayFormat = null)
+ {
+ var dxColumn = dxGridView.Columns.AddField(dataSourcePropertyName);
+ dxColumn.Caption = columnCaption;
+ dxColumn.VisibleIndex = dxGridView.Columns.Count - 1;
+ dxColumn.OptionsColumn.ReadOnly = readOnly;
+ dxColumn.Width = width;
+
+ var column = new TableViewColumn(dxGridView, dxGridControl, dxColumn, this, false);
+
+ if (displayFormat != null)
+ {
+ column.DisplayFormat = displayFormat;
+ }
+
+ columns.Add(column);
+ }
+
+ public void ClearColumns()
+ {
+ dxGridView.Columns.Clear();
+ columns.Clear();
+ }
+
+ public void Remove(TableViewColumn column)
+ {
+ if (columns.Remove(column))
+ {
+ dxGridView.Columns.Remove(column.DxColumn);
+ }
+ }
+
+ public void RemoveAllWhere(Func whereClause)
+ {
+ foreach (var tableViewColumn in columns.Where(whereClause).ToArray())
+ {
+ Remove(tableViewColumn);
+ }
+ }
+
+ ///
+ /// Adds an unbound column to the table. (Use to set values for the column)
+ ///
+ /// Name of the column
+ /// Type of the data the column is going to display
+ /// Index of the column
+ /// Editor to use for editing the values of this column
+ public void AddUnboundColumn(string columnName, Type columnType, int index = -1, Editors.ITypeEditor editor = null)
+ {
+ var unbColumn = dxGridView.Columns.AddField(columnName);
+ var column = new TableViewColumn(dxGridView, dxGridControl, unbColumn, this, true);
+ columns.Add(column);
+
+ unbColumn.VisibleIndex = index != -1 ? index : dxGridView.Columns.Count;
+
+ if (columnType == typeof(double))
+ {
+ unbColumn.UnboundType = UnboundColumnType.Decimal;
+ unbColumn.DisplayFormat.FormatType = FormatType.Numeric;
+ }
+ else if (columnType == typeof(int))
+ {
+ unbColumn.UnboundType = UnboundColumnType.Integer;
+ unbColumn.DisplayFormat.FormatType = FormatType.Numeric;
+ }
+ else if (columnType == typeof(string))
+ {
+ unbColumn.UnboundType = UnboundColumnType.String;
+ unbColumn.DisplayFormat.FormatType = FormatType.None;
+ }
+ else if (columnType.IsEnum)
+ {
+ unbColumn.UnboundType = UnboundColumnType.Object;
+ }
+ else if (columnType == typeof(DateTime))
+ {
+ unbColumn.UnboundType = UnboundColumnType.DateTime;
+ unbColumn.DisplayFormat.FormatType = FormatType.Custom;
+ }
+ else
+ {
+ throw new ArgumentException(string.Format(Resources.TableView_AddUnboundColumn_Unbound_columns_of_type_0_not_supported, columnType));
+ }
+ if (editor != null)
+ {
+ column.Editor = editor;
+ }
+
+ dxGridView.CustomUnboundColumnData -= DxGridViewCustomUnboundColumnData;
+ dxGridView.CustomUnboundColumnData += DxGridViewCustomUnboundColumnData;
+ }
+
+ public string GetCellDisplayText(int rowIndex, int absoluteColumnIndex)
+ {
+ return dxGridView.GetDisplayTextByColumnValue(dxGridView.Columns[absoluteColumnIndex], GetCellValue(rowIndex, absoluteColumnIndex));
+ }
+
+ #endregion
+
+ #region Public events
+
+ public event EventHandler FocusedRowChanged;
+
+ public event EventHandler SelectionChanged;
+
+ public event EventHandler> CellChanged;
+
+ public event EventHandler> ColumnFilterChanged;
+
+ #endregion
+
+ #region Internal functions
+
+ ///
+ /// Returns true when any column is sorted
+ ///
+ internal bool IsSorted()
+ {
+ return columns.Any(c => c.SortOrder != SortOrder.None);
+ }
+
+ internal TableViewCell GetFocusedCell()
+ {
+ //no selection
+ if (dxGridView.FocusedColumn == null)
+ {
+ return null;
+ }
+ //no row selected
+ if (dxGridView.FocusedRowHandle == int.MinValue)
+ {
+ return null;
+ }
+ //'new' row..select the bottom
+ if (dxGridView.FocusedRowHandle == (int.MinValue + 1))
+ {
+ var rowIndex = Math.Max(0, dxGridView.RowCount - 1);
+ return new TableViewCell(rowIndex, GetColumnByDxColumn(dxGridView.FocusedColumn));
+ }
+ return new TableViewCell(dxGridView.FocusedRowHandle, GetColumnByDxColumn(dxGridView.FocusedColumn));
+ }
+
+ internal void SetColumnError(TableViewColumn tableColumn, string errorText)
+ {
+ var dxGridColumn = tableColumn != null ? dxGridView.Columns[tableColumn.AbsoluteIndex] : null;
+ dxGridView.SetColumnError(dxGridColumn, errorText);
+ }
+
+ internal void AddNewRowToDataSource()
+ {
+ if (bindingSource == null)
+ {
+ bindingSource = new BindingSource
+ {
+ DataSource = dxGridView.DataSource
+ };
+ }
+
+ if (!bindingSource.AllowNew)
+ {
+ Log.Debug(Resources.TableView_AddNewRowToDataSource_Adding_rows_to_this_table_is_not_allowed);
+ return;
+ }
+ bindingSource.AddNew();
+
+ //end edit is needed when we bind to datatable
+ if (bindingSource.DataSource is DataTable || bindingSource.DataSource is DataView)
+ {
+ bindingSource.EndEdit();
+ }
+ }
+
+ internal TableViewColumn GetColumnByDisplayIndex(int i)
+ {
+ return columns.FirstOrDefault(c => c.DisplayIndex == i);
+ }
+
+ #endregion
+
+ #region Gridview event handlers
+
+ private void EmbeddedNavigatorButtonClick(object sender, NavigatorButtonClickEventArgs e)
+ {
+ if (e.Button != dxGridControl.EmbeddedNavigator.Buttons.Remove)
+ {
+ return;
+ }
+
+ // reroute delete event to "our" delete function
+ e.Handled = true;
+ DeleteCurrentSelection();
+ }
+
+ ///
+ /// Do keyboard cursor interaction like in Excel (StackOverflow: (c)Jakob M�ll�s)
+ ///
+ ///
+ ///
+ private void DxGridControlEditorKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Enter && UserIsHoldingDownControlForCellFill())
+ {
+ // grab selected cells here because changing the first value may cause the
+ // data source to refresh and the selection to be lost
+ cellsToFill = dxGridView.GetSelectedCells();
+ return;
+ }
+
+ if (e.KeyData != Keys.Left && e.KeyData != Keys.Right)
+ {
+ return;
+ }
+
+ var gridControl = sender as GridControl;
+ if (gridControl == null)
+ {
+ return;
+ }
+
+ var view = gridControl.FocusedView as GridView;
+ if (view == null)
+ {
+ return;
+ }
+
+ var textEdit = view.ActiveEditor as TextEdit;
+ if (textEdit == null)
+ {
+ return;
+ }
+
+ var left = e.KeyData == Keys.Left;
+ var right = e.KeyData == Keys.Right;
+
+ // Handle initial case - everything selected in control
+ if ((left || right) &&
+ textEdit.SelectionLength == textEdit.Text.Length &&
+ textEdit.SelectionStart == 0)
+ {
+ textEdit.SelectionStart = left ? 0 : textEdit.Text.Length; //minor adjustment
+ textEdit.SelectionLength = 0;
+ e.Handled = true;
+ return;
+ }
+
+ // Handle left & rightmost positions (prevent focus change)
+ e.Handled = left && textEdit.SelectionStart == 0 ||
+ right && textEdit.SelectionStart == textEdit.Text.Length;
+ }
+
+ private void DxGridViewDoubleClick(object sender, EventArgs e)
+ {
+ OnDoubleClick(e);
+ }
+
+ private void DxGridViewCustomDrawCell(object sender, RowCellCustomDrawEventArgs e)
+ {
+ var tableViewColumn = GetColumnByDxColumn(e.Column);
+
+ var buttonControl = tableViewColumn.Editor as ButtonTypeEditor;
+ if (buttonControl == null || !buttonControl.HideOnReadOnly)
+ {
+ return;
+ }
+
+ var cellReadOnly = CellIsReadOnly(e.RowHandle, tableViewColumn);
+ if (!cellReadOnly)
+ {
+ return;
+ }
+
+ var buttonEditViewInfo = ((GridCellInfo) e.Cell).ViewInfo as ButtonEditViewInfo;
+ if ((buttonEditViewInfo == null) || (buttonEditViewInfo.RightButtons.Count != 1))
+ {
+ return;
+ }
+
+ e.Appearance.FillRectangle(new GraphicsCache(e.Graphics), e.Bounds);
+ e.Handled = true;
+ }
+
+ private void DxGridViewColumnFilterChanged(object sender, EventArgs e)
+ {
+ if (ColumnFilterChanged == null)
+ {
+ return;
+ }
+
+ var selectedColumn = columns.OfType()
+ .FirstOrDefault(c => c.DxColumn == dxGridView.FocusedColumn);
+
+ ColumnFilterChanged(sender, new EventArgs(selectedColumn));
+ }
+
+ private void DxGridViewCustomDrawRowIndicator(object sender, RowIndicatorCustomDrawEventArgs e)
+ {
+ if (!showRowNumbers)
+ {
+ return;
+ }
+
+ // check whether the indicator cell belongs to a data row
+ if (e.Info.IsRowIndicator && e.RowHandle >= 0)
+ {
+ e.Info.DisplayText = (e.RowHandle + 1).ToString(CultureInfo.InvariantCulture);
+ e.Info.ImageIndex = -1;
+ e.Info.Appearance.TextOptions.HAlignment = HorzAlignment.Far;
+
+ if (FocusedRowIndex == e.RowHandle)
+ {
+ e.Info.ImageIndex = 0;
+ }
+ }
+ }
+
+ private void DxGridViewShowDxGridMenu(object sender, GridMenuEventArgs e)
+ {
+ bool first = true;
+
+ if (e.MenuType == GridMenuType.Column)
+ {
+ TableViewColumn tableViewColumn = null;
+
+ if (e.HitInfo.Column != null) //on a column
+ {
+ tableViewColumn = columns.FirstOrDefault(c => c.Caption == e.HitInfo.Column.GetTextCaption());
+ }
+
+ UpdateColumnHeaderMenu(e, tableViewColumn);
+
+ foreach (var menuItem in ColumnMenuItems.Where(menuItem => menuItem.ShouldShow(tableViewColumn)))
+ {
+ if (first)
+ {
+ menuItem.InternalItem.BeginGroup = true;
+ first = false;
+ }
+ else
+ {
+ menuItem.InternalItem.BeginGroup = false;
+ }
+
+ e.Menu.Items.Add(menuItem.InternalItem);
+ }
+ }
+ }
+
+ private void DxGridView2RowCellStyle(object sender, RowCellStyleEventArgs e)
+ {
+ var selected = ((!RowSelect && dxGridView.IsCellSelected(e.RowHandle, e.Column)) ||
+ (RowSelect && dxGridView.IsRowSelected(e.RowHandle)));
+
+ if (DisplayCellFilter != null)
+ {
+ var tableViewCellStyle = new TableViewCellStyle(e.RowHandle, GetColumnByDxColumn(e.Column), selected)
+ {
+ ForeColor = e.Appearance.ForeColor,
+ BackColor = e.Appearance.BackColor
+ };
+
+ if (DisplayCellFilter(tableViewCellStyle))
+ {
+ e.Appearance.ForeColor = tableViewCellStyle.ForeColor;
+ e.Appearance.BackColor = tableViewCellStyle.BackColor;
+ return;
+ }
+ }
+
+ if (selected)
+ {
+ e.Appearance.ForeColor = Color.White;
+ e.Appearance.BackColor = SystemColors.Highlight;
+ return;
+ }
+
+ var isReadOnly = CellIsReadOnly(e.RowHandle, GetColumnByDxColumn(e.Column));
+ if (isReadOnly)
+ {
+ e.Appearance.ForeColor = ReadOnlyCellForeColor;
+ e.Appearance.BackColor = ReadOnlyCellBackColor;
+ }
+
+ if (InvalidCellFilter == null)
+ {
+ return;
+ }
+ if (InvalidCellFilter(new TableViewCell(e.RowHandle, GetColumnByDxColumn(e.Column))))
+ {
+ e.Appearance.BackColor = InvalidCellBackgroundColor;
+ }
+ }
+
+ private void DxGridViewShownEditor(object sender, EventArgs e)
+ {
+ var view = sender as GridView;
+ if (view == null)
+ {
+ return;
+ }
+
+ var textEditor = view.ActiveEditor as TextEdit;
+ if (f2Pressed && textEditor != null && textEditor.IsEditorActive)
+ {
+ textEditor.SelectionStart = textEditor.Text.Length;
+ }
+
+ var buttonEditor = view.ActiveEditor as ButtonEdit;
+ if (buttonEditor != null)
+ {
+ buttonEditor.PerformClick(null);
+ }
+
+ dxGridControl.EmbeddedNavigator.Buttons.Append.Enabled = AllowAddNewRow && !OnNewRow();
+
+ f2Pressed = false;
+ }
+
+ private void DxGridViewShowingEditor(object sender, CancelEventArgs e)
+ {
+ var view = sender as GridView;
+ if (view == null)
+ {
+ return;
+ }
+
+ e.Cancel = CellIsReadOnly(view.FocusedRowHandle, GetColumnByDxColumn(view.FocusedColumn));
+ }
+
+ private void DxGridControlProcessDxGridKey(object sender, KeyEventArgs e)
+ {
+ f2Pressed = e.KeyCode == Keys.F2;
+
+ //TODO: get to switch like stament
+ if (((e.Shift) && (e.KeyCode == Keys.Insert)) ||
+ ((e.Control) && (e.KeyCode == Keys.V)))
+ {
+ //paste the glipboard if we are not editing a cell
+ if ((dxGridView.OptionsBehavior.Editable) && (dxGridView.State != GridState.Editing))
+ {
+ PasteClipboardContents();
+ //we need to suppres ctrl + v for being passing to child
+ //controls. Others wise the column goes into an editing state
+ e.SuppressKeyPress = true;
+ e.Handled = true;
+ }
+ }
+ if (((e.Control) && (e.KeyCode == Keys.Insert)) ||
+ ((e.Control) && (e.KeyCode == Keys.C)))
+ {
+ CopySelectionToClipboard();
+ e.Handled = true; //prevent XtraGrid from doing another copy resulting in an exception
+ }
+ if ((e.KeyCode == Keys.Delete) && (dxGridView.State == GridState.Normal))
+ {
+ DeleteCurrentSelection();
+ }
+
+ if (e.KeyCode == Keys.Enter && IsEndEditOnEnterKey && (dxGridView.IsEditing || OnNewRow()))
+ {
+ dxGridControl.EmbeddedNavigator.Buttons.DoClick(dxGridControl.EmbeddedNavigator.Buttons.EndEdit);
+ e.Handled = true;
+ e.SuppressKeyPress = true;
+ }
+ }
+
+ private void DxGridViewFocusedColumnChanged(object sender, FocusedColumnChangedEventArgs e)
+ {
+ if (e.FocusedColumn != null && !dxGridView.Columns.Contains(e.FocusedColumn))
+ {
+ // This is an awkward situation that can arise when a user clicks in the grid somewhere, after entering a value without Enter.
+ dxGridView.FocusedColumn = null;
+ }
+
+ ShowEditorIfRowSelect();
+ }
+
+ private void DxGridViewClick(object sender, EventArgs e)
+ {
+ var gridHitInfo = dxGridView.CalcHitInfo(PointToClient(MousePosition));
+
+ if (gridHitInfo.Column != null && gridHitInfo.Column.ColumnEdit is RepositoryItemButtonEdit)
+ {
+ dxGridView.ShowEditor(); // Reduces the number of clicks needed to actually click buttons by one
+ }
+
+ if (gridHitInfo.InColumn && (!gridHitInfo.InColumnPanel && RowSelect) && gridHitInfo.Column != null)
+ {
+ var columnIndex = gridHitInfo.Column.VisibleIndex;
+ if (((ModifierKeys & Keys.Control) == Keys.Control))
+ {
+ if (!DeselectSelectCells(0, columnIndex, dxGridView.RowCount - 1, columnIndex))
+ {
+ SelectCells(0, columnIndex, dxGridView.RowCount - 1, columnIndex, false);
+ }
+ }
+ else
+ {
+ SelectCells(0, columnIndex, dxGridView.RowCount - 1, columnIndex, true);
+ }
+ }
+
+ //bubble click..
+ OnClick(e);
+ }
+
+ ///
+ /// Called when a cell value is validated and the new value is set to the current cell.
+ /// If the user presses CTRL+ENTER the new value is copied to all selected cells. This
+ /// mimics the behaviour in Excel XP.
+ /// TODO: when the user presses cancel after the CTRL+ENTER only the current cell is reset.
+ ///
+ private void DxGridViewCellValueChanged(object sender, CellValueChangedEventArgs e)
+ {
+ if (UserIsHoldingDownControlForCellFill())
+ {
+ // temporarily disable value changed event
+ dxGridView.CellValueChanged -= DxGridViewCellValueChanged;
+
+ try
+ {
+ if (cellsToFill == null)
+ {
+ return;
+ }
+
+ foreach (GridCell gridcell in cellsToFill)
+ {
+ // only set new value to cell of same type
+ // todo add support for mixing double, float and int?
+ if (gridcell.Column.ColumnType == e.Value.GetType())
+ {
+ dxGridView.SetRowCellValue(gridcell.RowHandle, gridcell.Column, e.Value);
+ }
+ }
+ }
+ finally
+ {
+ dxGridView.CellValueChanged += DxGridViewCellValueChanged;
+ cellsToFill = null;
+ }
+ }
+ if (CellChanged != null)
+ {
+ CellChanged(this, new EventArgs(new TableViewCell(e.RowHandle, GetColumnByDxColumn(e.Column))));
+ }
+ }
+
+ private bool UserIsHoldingDownControlForCellFill()
+ {
+ return MultipleCellEdit && ModifierKeys == Keys.Control && !isPasting;
+ }
+
+ private void DxGridViewSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (!isSelectionChanging)
+ {
+ isSelectionChanging = true;
+ }
+ UpdateSelectionFromGridControl();
+ }
+
+ private void DxGridViewFocusedRowChanged(object sender, FocusedRowChangedEventArgs e)
+ {
+ if (FocusedRowChanged != null)
+ {
+ FocusedRowChanged(sender, EventArgs.Empty);
+ }
+ }
+
+ private void DxGridViewCustomUnboundColumnData(object sender, CustomColumnDataEventArgs e)
+ {
+ if (UnboundColumnData == null)
+ {
+ return;
+ }
+
+ var result = UnboundColumnData(e.Column.AbsoluteIndex, e.ListSourceRowIndex, e.IsGetData, e.IsSetData, e.Value);
+ if (result != null)
+ {
+ e.Value = result;
+ }
+ }
+
+ private void DxGridViewMouseEnter(object sender, EventArgs e)
+ {
+ OnMouseEnter(e);
+ }
+
+ private void DxGridViewMouseDown(object sender, MouseEventArgs e)
+ {
+ // Check edit single click when in cell select mode
+ // http://www1.devexpress.com/Support/Center/p/Q144046.aspx
+ if ((ModifierKeys & Keys.Control) != Keys.Control && (ModifierKeys & Keys.Shift) != Keys.Shift)
+ {
+ var hi = dxGridView.CalcHitInfo(e.Location);
+ if (hi.InRowCell && hi.Column.RealColumnEdit.GetType() == typeof(RepositoryItemCheckEdit))
+ {
+ dxGridView.FocusedRowHandle = hi.RowHandle;
+ dxGridView.FocusedColumn = hi.Column;
+ dxGridView.ShowEditor();
+
+ // get active editor or create one (when cell is readonly and no ActiveEditor is set)
+ var checkEdit = (dxGridView.ActiveEditor ?? hi.Column.RealColumnEdit.CreateEditor()) as CheckEdit;
+ if (checkEdit != null)
+ {
+ var checkInfo = (CheckEditViewInfo) checkEdit.GetViewInfo();
+ var glyphRect = checkInfo.CheckInfo.GlyphRect;
+
+ var viewInfo = dxGridView.GetViewInfo() as GridViewInfo;
+ if (viewInfo != null)
+ {
+ var gridGlyphRect = new Rectangle(viewInfo.GetGridCellInfo(hi).Bounds.X + glyphRect.X,
+ viewInfo.GetGridCellInfo(hi).Bounds.Y + glyphRect.Y,
+ glyphRect.Width,
+ glyphRect.Height);
+
+ dxGridView.ClearSelection();
+
+ if (!gridGlyphRect.Contains(e.Location))
+ {
+ dxGridView.CloseEditor();
+ if (!RowSelect)
+ {
+ if (!dxGridView.IsCellSelected(hi.RowHandle, hi.Column))
+ {
+ dxGridView.SelectCell(hi.RowHandle, hi.Column);
+ }
+ else
+ {
+ dxGridView.UnselectCell(hi.RowHandle, hi.Column);
+ }
+ }
+ }
+ else
+ {
+ checkEdit.Checked = !checkEdit.Checked;
+ dxGridView.CloseEditor();
+ }
+
+ if (RowSelect)
+ {
+ dxGridView.SelectRow(hi.RowHandle);
+ }
+ }
+ }
+
+ var dxMouseEventArgs = e as DXMouseEventArgs;
+ if (dxMouseEventArgs != null)
+ {
+ dxMouseEventArgs.Handled = true;
+ }
+ }
+ }
+
+ HandleHeaderPanelButton(sender, e);
+ OnMouseDown(e);
+ }
+
+ private void DxGridViewInvalidRowException(object sender, InvalidRowExceptionEventArgs e)
+ {
+ switch (ExceptionMode)
+ {
+ case ValidationExceptionMode.Ignore:
+ e.ExceptionMode = DevExpress.XtraEditors.Controls.ExceptionMode.Ignore;
+ break;
+ case ValidationExceptionMode.NoAction:
+ e.ExceptionMode = DevExpress.XtraEditors.Controls.ExceptionMode.NoAction;
+ break;
+ case ValidationExceptionMode.DisplayError:
+ e.ExceptionMode = DevExpress.XtraEditors.Controls.ExceptionMode.DisplayError;
+ break;
+ case ValidationExceptionMode.ThrowException:
+ e.ExceptionMode = DevExpress.XtraEditors.Controls.ExceptionMode.ThrowException;
+ break;
+ }
+ }
+
+ private static void DxGridControlPreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
+ {
+ if (e.KeyCode == Keys.Enter)
+ {
+ e.IsInputKey = true; //do no use special processing
+ }
+ }
+
+ private void DxGridViewHiddenEditor(object sender, EventArgs e)
+ {
+ dxGridControl.EmbeddedNavigator.Buttons.Append.Enabled = AllowAddNewRow;
+ }
+
+ private void OnDxGridViewOnFocusedRowChanged(object o, FocusedRowChangedEventArgs args)
+ {
+ DxGridViewFocusedRowChanged(o, args);
+ }
+
+ #endregion
+
+ #region Initialization functions
+
+ private void ConfigureContextMenu()
+ {
+ var btnCopy = new ToolStripMenuItem
+ {
+ Name = "btnCopy", Image = Resources.CopyHS, Size = new Size(116, 22), Text = Resources.TableView_ConfigureContextMenu_Copy, Tag = "btnCopy"
+ };
+ var btnPaste = new ToolStripMenuItem
+ {
+ Name = "btnPaste", Image = Resources.PasteHS, Size = new Size(116, 22), Text = Resources.TableView_ConfigureContextMenu_Paste, Tag = "btnPaste"
+ };
+ var btnDelete = new ToolStripMenuItem
+ {
+ Name = "btnDelete", Image = Resources.DeleteHS1, Size = new Size(116, 22), Text = Resources.TableView_ConfigureContextMenu_Delete, Tag = "btnDelete"
+ };
+
+ btnCopy.Click += delegate { CopySelectionToClipboard(); };
+ btnPaste.Click += delegate { PasteClipboardContents(); };
+ btnDelete.Click += delegate { DeleteCurrentSelection(); };
+
+ var viewContextMenu = new ContextMenuStrip();
+ viewContextMenu.Items.AddRange(new ToolStripItem[]
+ {
+ btnCopy,
+ btnPaste,
+ btnDelete
+ });
+
+ RowContextMenu = viewContextMenu;
+ }
+
+ private void CreateRefreshTimer()
+ {
+ refreshTimer = new Timer();
+ refreshTimer.Tick += OnRefreshTimerOnTick;
+
+ refreshTimer.Interval = 300;
+ refreshTimer.Enabled = true;
+ refreshTimer.Start();
+ }
+
+ private void OnRefreshTimerOnTick(object sender, EventArgs e)
+ {
+ RefreshIfRequired();
+ }
+
+ private void SubscribeEvents()
+ {
+ // mouse events
+ dxGridView.Click += DxGridViewClick;
+ dxGridView.DoubleClick += DxGridViewDoubleClick;
+ dxGridView.MouseEnter += DxGridViewMouseEnter;
+ dxGridView.MouseDown += DxGridViewMouseDown;
+
+ dxGridView.InvalidRowException += DxGridViewInvalidRowException;
+
+ // keyboard events
+ dxGridControl.PreviewKeyDown += DxGridControlPreviewKeyDown;
+ dxGridControl.ProcessGridKey += DxGridControlProcessDxGridKey;
+
+ // change of focus
+ dxGridView.FocusedRowChanged += OnDxGridViewOnFocusedRowChanged;
+ dxGridView.FocusedRowChanged += tableViewValidator.RowLostFocus;
+ dxGridView.FocusedColumnChanged += DxGridViewFocusedColumnChanged;
+
+ // value changes
+ dxGridView.CellValueChanged += tableViewValidator.OnCellValueChanged;
+ dxGridView.CellValueChanged += DxGridViewCellValueChanged;
+
+ // filtering events
+ dxGridView.ColumnFilterChanged += DxGridViewColumnFilterChanged;
+
+ // drawing events
+ dxGridView.CustomDrawRowIndicator += DxGridViewCustomDrawRowIndicator;
+ dxGridView.CustomDrawCell += DxGridViewCustomDrawCell;
+ dxGridView.RowCellStyle += DxGridView2RowCellStyle;
+
+ // editor events
+ dxGridView.ShowingEditor += DxGridViewShowingEditor;
+ dxGridView.ShownEditor += DxGridViewShownEditor;
+ dxGridView.HiddenEditor += tableViewValidator.HiddenEditor;
+ dxGridView.HiddenEditor += DxGridViewHiddenEditor;
+
+ dxGridView.ValidatingEditor += (s, e) =>
+ {
+ var cell = new TableViewCell(FocusedRowIndex, GetColumnByDxColumn(dxGridView.FocusedColumn));
+ tableViewValidator.OnValidateCell(cell, e);
+ };
+ dxGridControl.EditorKeyDown += DxGridControlEditorKeyDown;
+
+ // selection events
+ dxGridView.SelectionChanged += DxGridViewSelectionChanged;
+
+ dxGridView.ShowGridMenu += DxGridViewShowDxGridMenu;
+ dxGridView.ValidateRow += tableViewValidator.OnValidateRow;
+ dxGridControl.EmbeddedNavigator.ButtonClick += EmbeddedNavigatorButtonClick;
+
+ PasteController.PasteFailed += CopyPasteControllerPasteFailed;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableView.resx
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableView.resx (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableView.resx (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableViewCell.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableViewCell.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableViewCell.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,21 @@
+namespace Core.Common.Controls.Table
+{
+ public class TableViewCell
+ {
+ public TableViewCell(int rowIndex, TableViewColumn column)
+ {
+ RowIndex = rowIndex;
+ Column = column;
+ }
+
+ ///
+ /// Row index of the cell
+ ///
+ public int RowIndex { get; set; }
+
+ ///
+ /// Column of the cell
+ ///
+ public TableViewColumn Column { get; set; }
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableViewCellFormatterProvider.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableViewCellFormatterProvider.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableViewCellFormatterProvider.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,31 @@
+using System;
+
+namespace Core.Common.Controls.Table
+{
+ ///
+ /// Wrapper for ICustomFormatter, so that IFormatProvider won't have to be implemented.
+ /// http://documentation.devexpress.com/#WindowsForms/CustomDocument3045
+ ///
+ public class TableViewCellFormatterProvider : IFormatProvider
+ {
+ private readonly ICustomFormatter formatter;
+
+ public TableViewCellFormatterProvider(ICustomFormatter formatter)
+ {
+ this.formatter = formatter;
+ }
+
+ ///
+ /// Returns an object that provides formatting services for the specified type.
+ ///
+ ///
+ /// An instance of the object specified by ,
+ /// if the implementation can supply that type of object; otherwise, null.
+ ///
+ /// An object that specifies the type of format object to return.
+ public object GetFormat(Type formatType)
+ {
+ return formatter;
+ }
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableViewCellStyle.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableViewCellStyle.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableViewCellStyle.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,18 @@
+using System.Drawing;
+
+namespace Core.Common.Controls.Table
+{
+ public class TableViewCellStyle : TableViewCell
+ {
+ public TableViewCellStyle(int rowIndex, TableViewColumn column, bool selected) : base(rowIndex, column)
+ {
+ Selected = selected;
+ }
+
+ public Color ForeColor { get; set; }
+
+ public Color BackColor { get; set; }
+
+ public bool Selected { get; private set; }
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableViewColumn.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableViewColumn.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableViewColumn.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,410 @@
+using System;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using Core.Common.Controls.Table.Properties;
+using DevExpress.Data;
+using DevExpress.Utils;
+using DevExpress.XtraGrid;
+using DevExpress.XtraGrid.Columns;
+using DevExpress.XtraGrid.Views.Grid;
+
+namespace Core.Common.Controls.Table
+{
+ public class TableViewColumn
+ {
+ private readonly GridView dxGridView;
+ private readonly GridColumn dxColumn;
+ private readonly TableView tableView;
+ private readonly GridControl dxGridControl;
+ private Editors.ITypeEditor editor;
+
+ private string displayFormat = "";
+ private int visibleIndex;
+ private ICustomFormatter customFormatter;
+
+ public TableViewColumn(GridView view, GridControl control, GridColumn column, TableView tableView, bool unbound)
+ {
+ dxGridView = view;
+ dxGridControl = control;
+ dxColumn = column;
+ this.tableView = tableView;
+ IsUnbound = unbound;
+
+ dxColumn.FilterMode = dxColumn.ColumnType == typeof(DateTime) ||
+ dxColumn.ColumnType == typeof(double) ||
+ dxColumn.ColumnType == typeof(int)
+ ? ColumnFilterMode.Value
+ : ColumnFilterMode.DisplayText;
+ dxColumn.OptionsColumn.AllowMove = false;
+ }
+
+ public bool FilteringAllowed
+ {
+ get
+ {
+ return dxColumn.OptionsFilter.AllowFilter;
+ }
+ set
+ {
+ dxColumn.OptionsFilter.AllowFilter = value;
+ }
+ }
+
+ ///
+ /// The name of the column
+ ///
+ public string Name
+ {
+ // XtraGrid prefixes the Name with a "col", we need the FieldName for DataBinding
+ get
+ {
+ return dxColumn.FieldName;
+ }
+ }
+
+ public string Caption
+ {
+ get
+ {
+ return dxColumn.GetCaption();
+ } //get actual displayed value
+ set
+ {
+ dxColumn.Caption = value;
+ } //set custom value
+ }
+
+ public int DisplayIndex
+ {
+ get
+ {
+ return dxColumn.VisibleIndex;
+ }
+ set
+ {
+ dxColumn.VisibleIndex = value;
+ }
+ }
+
+ public object DefaultValue { get; set; }
+
+ public bool IsUnbound { get; private set; }
+
+ ///
+ /// Index of the column in column collection of the gridview.
+ /// This collection includes invisible columns etc
+ ///
+ public int AbsoluteIndex
+ {
+ get
+ {
+ return dxColumn.AbsoluteIndex;
+ }
+ set
+ {
+ dxColumn.AbsoluteIndex = value;
+ }
+ }
+
+ ///
+ /// Allows to override the way cell text is rendered.
+ ///
+ /// Will reset
+ ///
+ public ICustomFormatter CustomFormatter
+ {
+ get
+ {
+ return customFormatter;
+ }
+ set
+ {
+ customFormatter = value;
+
+ SetXtraGridCustomFormatterCore(dxColumn.DisplayFormat, value);
+ if (dxColumn.ColumnEdit != null)
+ {
+ SetXtraGridCustomFormatterCore(dxColumn.ColumnEdit.DisplayFormat, value);
+ }
+ }
+ }
+
+ ///
+ /// Sets the displayformat of the column. For example c2, D or AA{0}
+ /// If CustomFormatter is used then this property is skipped.
+ ///
+ public string DisplayFormat
+ {
+ get
+ {
+ return displayFormat;
+ }
+ set
+ {
+ displayFormat = value;
+ SetXtraGridDisplayFormat(value);
+ }
+ }
+
+ public bool Pinned
+ {
+ get
+ {
+ return dxColumn.Fixed == FixedStyle.Left;
+ }
+ set
+ {
+ dxColumn.Fixed = (value ? FixedStyle.Left : FixedStyle.None);
+ if (!Pinned)
+ {
+ // Restore original display index
+ var unPinnedColumns = tableView.Columns.Where(c => !c.Pinned).ToList();
+ var columnToTheLeft = unPinnedColumns.LastOrDefault(c => c.AbsoluteIndex < AbsoluteIndex);
+ DisplayIndex = columnToTheLeft != null
+ ? columnToTheLeft.DisplayIndex + 1
+ : tableView.Columns.Count - unPinnedColumns.Count;
+ }
+ }
+ }
+
+ ///
+ /// The visibility of the column
+ ///
+ public bool Visible
+ {
+ get
+ {
+ return dxColumn.Visible;
+ }
+ set
+ {
+ dxColumn.Visible = value;
+ // Table BestFitColumns ignores columns with AllowSize set to false; It does noet use the visible
+ // property. For best performance disable AllowSize if column is hidden.
+ dxColumn.OptionsColumn.AllowSize = dxColumn.Visible;
+ if (!value)
+ {
+ // remember old column index
+ if (dxColumn.VisibleIndex != -1)
+ {
+ visibleIndex = dxColumn.VisibleIndex;
+ }
+ dxColumn.VisibleIndex = -1;
+ }
+ else
+ {
+ dxColumn.VisibleIndex = visibleIndex;
+ }
+ }
+ }
+
+ public Editors.ITypeEditor Editor
+ {
+ get
+ {
+ return editor;
+ }
+ set
+ {
+ if (value == null)
+ {
+ return;
+ }
+
+ editor = value;
+
+ var repositoryItem = XtraGridRepositoryItemBuilder.CreateFromTypeEditor(editor, dxGridControl, dxColumn, Caption);
+ dxGridControl.RepositoryItems.Add(repositoryItem);
+ dxColumn.ColumnEdit = repositoryItem;
+ }
+ }
+
+ public int Width
+ {
+ get
+ {
+ return dxColumn.Width;
+ }
+ set
+ {
+ dxColumn.Width = value;
+ }
+ }
+
+ public bool SortingAllowed
+ {
+ get
+ {
+ return dxColumn.OptionsColumn.AllowSort != DefaultBoolean.False;
+ }
+ set
+ {
+ dxColumn.OptionsColumn.AllowSort = (value) ? DefaultBoolean.True : DefaultBoolean.False;
+ }
+ }
+
+ ///
+ /// Get or set column filter. Use a syntax like "[Naam] = 'kees'"
+ ///
+ public string FilterString
+ {
+ get
+ {
+ return dxColumn.FilterInfo.FilterString;
+ }
+ set
+ {
+ dxColumn.FilterInfo = new ColumnFilterInfo(value);
+ }
+ }
+
+ ///
+ /// Set the column sortorder.
+ ///
+ public SortOrder SortOrder
+ {
+ get
+ {
+ //some conversion between sortorders :(
+ //who needs more??
+ switch (dxColumn.SortOrder)
+ {
+ case ColumnSortOrder.Ascending:
+ return SortOrder.Ascending;
+ case ColumnSortOrder.Descending:
+ return SortOrder.Descending;
+ default:
+ return SortOrder.None;
+ }
+ }
+ set
+ {
+ switch (value)
+ {
+ case SortOrder.None:
+ dxColumn.SortOrder = ColumnSortOrder.None;
+ break;
+ case SortOrder.Ascending:
+ dxColumn.SortOrder = ColumnSortOrder.Ascending;
+ break;
+ case SortOrder.Descending:
+ dxColumn.SortOrder = ColumnSortOrder.Descending;
+ break;
+ }
+ }
+ }
+
+ public Type ColumnType
+ {
+ get
+ {
+ var type = typeof(object);
+ try
+ {
+ if (dxColumn.ColumnHandle != -1)
+ {
+ type = dxColumn.ColumnType;
+ }
+ }
+ catch (NullReferenceException)
+ {
+ //gulp: can throw nullreference exception for some reason
+ }
+ return type;
+ }
+ }
+
+ public string ToolTip
+ {
+ get
+ {
+ return dxColumn.ToolTip;
+ }
+ set
+ {
+ dxColumn.ToolTip = value;
+ }
+ }
+
+ public bool ReadOnly
+ {
+ get
+ {
+ return dxColumn.OptionsColumn.ReadOnly;
+ }
+ set
+ {
+ dxColumn.OptionsColumn.AllowEdit = !value; // false;
+ dxColumn.OptionsColumn.ReadOnly = value;
+ //copy readonly style from tableview
+ if (dxColumn.OptionsColumn.ReadOnly)
+ {
+ dxColumn.AppearanceCell.ForeColor = tableView.ReadOnlyCellForeColor;
+ dxColumn.AppearanceCell.BackColor = tableView.ReadOnlyCellBackColor;
+ }
+ else
+ {
+ //reset to defaults
+ dxColumn.AppearanceCell.ForeColor = Color.Empty;
+ //'empty'
+ dxColumn.AppearanceCell.BackColor = Color.Empty;
+ // dxColumn.AppearanceCell.BackColor = Color.White;
+ }
+ }
+ }
+
+ public void Dispose()
+ {
+ if (editor != null)
+ {
+ editor.Dispose();
+ }
+ }
+
+ internal GridColumn DxColumn
+ {
+ get
+ {
+ return dxColumn;
+ }
+ }
+
+ private void SetXtraGridDisplayFormat(string value)
+ {
+ SetXtraGridDisplayFormatCore(dxColumn.DisplayFormat, value);
+ if (dxColumn.ColumnEdit != null)
+ {
+ SetXtraGridDisplayFormatCore(dxColumn.ColumnEdit.DisplayFormat, value);
+ }
+ }
+
+ private void SetXtraGridDisplayFormatCore(FormatInfo dxFormatInfo, string value)
+ {
+ dxFormatInfo.FormatType = GetFormatType(value);
+ dxFormatInfo.FormatString = value;
+ }
+
+ private static void SetXtraGridCustomFormatterCore(FormatInfo dxFormatInfo, ICustomFormatter value)
+ {
+ if (value == null)
+ {
+ dxFormatInfo.FormatType = FormatType.None;
+ return;
+ }
+
+ dxFormatInfo.FormatType = FormatType.Custom;
+ dxFormatInfo.Format = new TableViewCellFormatterProvider(value);
+ dxFormatInfo.FormatString = Resources.TableViewColumn_SetXtraGridCustomFormatterCore_custom; //must be non null/empty for custom formatting to work
+ }
+
+ private FormatType GetFormatType(string value)
+ {
+ return string.IsNullOrEmpty(value)
+ ? FormatType.None
+ : (ColumnType == typeof(DateTime)
+ ? FormatType.DateTime
+ : FormatType.Numeric);
+ }
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableViewColumnMenuItem.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableViewColumnMenuItem.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableViewColumnMenuItem.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,72 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using DevExpress.Utils.Menu;
+
+namespace Core.Common.Controls.Table
+{
+ public class TableViewColumnMenuItem
+ {
+ public event EventHandler Click;
+
+ public event CancelEventHandler Showing;
+ private readonly DXMenuItem internalItem;
+
+ public TableViewColumnMenuItem(string caption)
+ {
+ internalItem = new DXMenuItem(caption);
+ internalItem.Click += InternalItemClick;
+ }
+
+ public DXMenuItem InternalItem
+ {
+ get
+ {
+ return internalItem;
+ }
+ }
+
+ public string Caption
+ {
+ get
+ {
+ return internalItem.Caption;
+ }
+ }
+
+ public Image Image
+ {
+ get
+ {
+ return internalItem.Image;
+ }
+ set
+ {
+ internalItem.Image = value;
+ }
+ }
+
+ public bool ShouldShow(TableViewColumn column)
+ {
+ if (Showing != null)
+ {
+ var args = new CancelEventArgs();
+ Showing(column, args);
+ if (args.Cancel)
+ {
+ return false;
+ }
+ }
+ internalItem.Tag = column;
+ return true;
+ }
+
+ private void InternalItemClick(object sender, EventArgs e)
+ {
+ if (Click != null)
+ {
+ Click(internalItem.Tag, e);
+ }
+ }
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableViewComboBoxItem.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableViewComboBoxItem.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableViewComboBoxItem.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,119 @@
+using System;
+using Core.Common.Utils;
+
+namespace Core.Common.Controls.Table
+{
+ public class TableViewComboBoxItem : IConvertible
+ {
+ public object Value { get; set; }
+
+ public string DisplayText
+ {
+ get
+ {
+ if (CustomFormatter != null)
+ {
+ return CustomFormatter.Format(null, Value, null);
+ }
+
+ return Value.ToString();
+ }
+ }
+
+ public ICustomFormatter CustomFormatter { get; set; }
+
+ public override string ToString()
+ {
+ return Value != null ? Value.ToString() : "null";
+ }
+
+ #region Implementation of IConvertible
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.String;
+ }
+
+ public bool ToBoolean(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public char ToChar(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public sbyte ToSByte(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public byte ToByte(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public short ToInt16(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ushort ToUInt16(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int ToInt32(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public uint ToUInt32(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public long ToInt64(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ulong ToUInt64(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public float ToSingle(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public double ToDouble(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public decimal ToDecimal(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public DateTime ToDateTime(IFormatProvider provider)
+ {
+ throw new NotImplementedException();
+ }
+
+ public string ToString(IFormatProvider provider)
+ {
+ return ToString();
+ }
+
+ public object ToType(Type conversionType, IFormatProvider provider)
+ {
+ return Value;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableViewExceptionMessageController.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableViewExceptionMessageController.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableViewExceptionMessageController.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,15 @@
+using Core.Common.Controls.Table.Properties;
+using DevExpress.XtraGrid.Localization;
+
+namespace Core.Common.Controls.Table
+{
+ public class TableViewExceptionMessageController : GridLocalizer
+ {
+ public override string GetLocalizedString(GridStringId id)
+ {
+ return id == GridStringId.ColumnViewExceptionMessage
+ ? Resources.TableViewExceptionMessageController_GetLocalizedString
+ : base.GetLocalizedString(id);
+ }
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableViewPasteBehaviourOptions.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableViewPasteBehaviourOptions.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableViewPasteBehaviourOptions.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,8 @@
+namespace Core.Common.Controls.Table
+{
+ public enum TableViewPasteBehaviourOptions
+ {
+ SkipCellWhenValueIsInvalid,
+ SkipRowWhenValueIsInvalid
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/TableViewPasteController.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/TableViewPasteController.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/TableViewPasteController.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,541 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+using Core.Common.Controls.Table.Properties;
+using Core.Common.Utils.Events;
+
+using log4net;
+
+namespace Core.Common.Controls.Table
+{
+ ///
+ /// Class add copy paste functionality to a tableview. Based on ITableView
+ ///
+ public class TableViewPasteController
+ {
+ public event EventHandler> PasteFailed;
+
+ public event EventHandler PasteFinished;
+
+ private const int NewRowSelectedIndex = int.MinValue + 1;
+ private static readonly ILog Log = LogManager.GetLogger(typeof(TableViewPasteController));
+
+ public TableViewPasteController(TableView tableView)
+ {
+ TableView = tableView;
+ PastedRows = new List();
+ PastedBlocks = new List();
+ }
+
+ ///
+ /// Gets or sets the paste behaviour value
+ ///
+ public TableViewPasteBehaviourOptions PasteBehaviour { get; set; }
+
+ public bool IsPasting { get; private set; }
+
+ ///
+ /// This method does most of the work. It Pastes Clipboard content to the XtraGrid.
+ /// If OptionsSelection.EnableAppearanceFocusedRow == true then it will paste row (if
+ /// any row is present in the clipboard) to the currently selected row. It will not
+ /// replace Readonly or Not Editable Fields as well as key fields for the child tables
+ /// and details. It works not on the XtraGrid level but on the DataTable level.
+ /// If the currently selected row in the XtraGrid is the New Row then it will populate
+ /// it with the values from the row in the Clipboard.
+ ///
+ public void PasteClipboardContents()
+ {
+ // for now only allow to paste text
+ if (!Clipboard.ContainsText())
+ {
+ Log.Debug(Resources.TableViewPasteController_PasteClipboardContents_Clipboard_does_not_contain_text_so_it_cannot_be_pasted_to_the_grid);
+ return;
+ }
+
+ string[] clipboardLines = GetClipboardLines();
+ //nothing to paste.
+ if (clipboardLines.Length == 0)
+ {
+ return;
+ }
+
+ PasteLines(clipboardLines);
+ }
+
+ ///
+ /// Paste value string into tableview at current selection
+ ///
+ ///
+ public void PasteLines(string[] lines)
+ {
+ IsPasting = true;
+
+ lines = RemoveHeaderIfPresent(lines);
+
+ //get the selection in which we are to paste
+ var targetSelection = GetPasteTargetSelection();
+ //check if we can paste or fail
+ string message;
+ if (!CanPaste(lines, out message))
+ {
+ OnPasteFailed(message);
+
+ IsPasting = false;
+
+ return; //don't paste
+ }
+
+ //pastevalues returns the pasted selection
+
+ var tableViewImpl = TableView as TableView;
+
+ if (tableViewImpl != null)
+ {
+ tableViewImpl.BeginInit();
+ }
+
+ PastedRows.Clear();
+ PastedBlocks.Clear();
+
+ PasteValues(lines, targetSelection, (!TableView.IsSorted()) && (TableView.AllowAddNewRow));
+
+ if (tableViewImpl != null)
+ {
+ tableViewImpl.EndInit();
+ }
+
+ SetSelection();
+
+ PastedRows.Clear();
+ PastedBlocks.Clear();
+
+ IsPasting = false;
+
+ OnPasteFinished();
+ }
+
+ protected TableView TableView { get; private set; }
+ protected List PastedBlocks { private get; set; }
+
+ ///
+ /// Overload without message parameter.
+ ///
+ ///
+ protected RectangleSelection GetPasteTargetSelection()
+ {
+ string message;
+ return GetPasteTargetSelection(out message);
+ }
+
+ ///
+ /// Gets the target selection from tableview or raises paste failed event in case
+ /// the target selection is invalid (non-rectangular)
+ ///
+ ///
+ protected RectangleSelection GetPasteTargetSelection(out string errorMessage)
+ {
+ errorMessage = "";
+
+ var topLeft = new TableViewCell(0, null);
+ //in RowSelect don't used selected cells because they don't work
+ if (TableView.RowSelect)
+ {
+ return GetRowSelectSelection();
+ }
+
+ var cells = TableView.SelectedCells.ToList();
+ if (cells.Count == 0)
+ {
+ //base selection on focused cell
+ var focusedCell = TableView.GetFocusedCell();
+ if (focusedCell != null)
+ {
+ return new RectangleSelection(focusedCell, focusedCell);
+ }
+ //no focused cell must mean empty table..start pasting left,top
+ return new RectangleSelection(topLeft, topLeft);
+ }
+
+ //return a selection based on the first and last cell in the selection. Tricky..should check the most upper etc..
+ RectangleSelection selection = GetRectangleSelection(cells);
+
+ if (selection == null)
+ {
+ errorMessage = Resources.TableViewPasteController_GetPasteTargetSelection_Cannot_paste_into_non_rectangular_selection;
+ }
+
+ return selection;
+ }
+
+ protected RectangleSelection GetRowSelectSelection()
+ {
+ var selectedRows = TableView.SelectedRowsIndices;
+ var topLeft = selectedRows.Length == 0
+ ? new TableViewCell(TableView.RowCount, TableView.GetColumnByDisplayIndex(0))
+ : new TableViewCell(selectedRows[0], TableView.GetColumnByDisplayIndex(0));
+
+ return new RectangleSelection(topLeft, topLeft);
+ }
+
+ ///
+ /// Returns rectangle for a collection of cells. Or null if cells don't make up a rectangle
+ ///
+ ///
+ ///
+ protected RectangleSelection GetRectangleSelection(IList cells)
+ {
+ int left = cells.Min(cell => cell.Column.DisplayIndex);
+ int right = cells.Max(cell => cell.Column.DisplayIndex);
+ int top = cells.Min(cell => cell.RowIndex);
+ int bottom = cells.Max(cell => cell.RowIndex);
+
+ //if the selection is on 'new' row change to rowcount..
+ if ((bottom == NewRowSelectedIndex) && (top == NewRowSelectedIndex))
+ {
+ bottom = TableView.RowCount;
+ top = TableView.RowCount;
+ }
+ //do a check if we have enought cells...
+ if (cells.Count != (right + 1 - left)*(bottom + 1 - top))
+ {
+ return null;
+ }
+
+ return new RectangleSelection(new TableViewCell(top, TableView.GetColumnByDisplayIndex(left)), new TableViewCell(bottom, TableView.GetColumnByDisplayIndex(right)));
+ }
+
+ ///
+ /// Checks whether the target tableView is filtered or the target selection contains a sorted column
+ ///
+ ///
+ ///
+ ///
+ protected virtual bool CanPaste(string[] clipboardLines, out string errorMessage)
+ {
+ //get a targetselection. Can fail if target is non square. Then error message is filled
+ var targetSelection = GetPasteTargetSelection(out errorMessage);
+ if (targetSelection == null)
+ {
+ return false;
+ }
+
+ if (clipboardLines.Length == 0)
+ {
+ errorMessage = Resources.TableViewPasteController_CanPaste_There_are_no_values_to_paste_Headers_are_skipped;
+ return false;
+ }
+
+ //how many columns do if hit when we paste?
+ var pasteColumnSpan = SplitToCells(clipboardLines[0]).Length;
+
+ int[] pastedColumnIndexes = Enumerable.Range(targetSelection.Left, pasteColumnSpan).ToArray();
+
+ //is there sorted column in our pasted columns?
+ var sortedColumnExists = (from col in TableView.Columns
+ where col.SortOrder != SortOrder.None && pastedColumnIndexes.Contains(col.DisplayIndex)
+ select col).Any();
+ if (sortedColumnExists)
+ {
+ errorMessage = Resources.TableViewPasteController_CanPaste_Cannot_paste_into_sorted_column; //todo: add name of column here?
+ return false;
+ }
+ if (TableView.Columns.Any(col => !string.IsNullOrEmpty(col.FilterString)))
+ {
+ errorMessage = Resources.TableViewPasteController_CanPaste_Cannot_paste_into_filtered_tableview; //todo: add name of column here?
+ return false;
+ }
+ return true;
+ }
+
+ ///
+ /// Pastes values into target selection.
+ ///
+ protected virtual void PasteValues(string[] clipboardLines, RectangleSelection targetSelection,
+ bool allowNewRows, bool wrapInEditAction = true)
+ {
+ if (wrapInEditAction)
+ {
+ PasteValuesCore(clipboardLines, targetSelection, allowNewRows);
+ }
+ else
+ {
+ PasteValuesCore(clipboardLines, targetSelection, allowNewRows);
+ }
+ }
+
+ ///
+ /// Pastes the given contents to the table at row startRowIndex, increasing the number of rows if necessary and allowed.
+ ///
+ /// The row index at which the pasting effectively occured, -1 if no pasting was done.
+ protected int PasteCellsToRow(string[] content, int startRowIndex, int startColumnIndex, int pasteWidth, bool addNewRow, bool cellBased)
+ {
+ var index = startRowIndex;
+ if (addNewRow)
+ {
+ TableView.AddNewRowToDataSource();
+ }
+ else
+ {
+ if (startRowIndex >= TableView.RowCount)
+ {
+ return -1;
+ }
+ }
+ var exceptionMode = TableView.ExceptionMode;
+ TableView.ExceptionMode = TableView.ValidationExceptionMode.ThrowException; //throw exception
+ try
+ {
+ if (cellBased)
+ {
+ var contentWidth = content.Length;
+ for (var i = 0; i < pasteWidth; i++)
+ {
+ if (!SafeSetCellValue(index, startColumnIndex + i, content[i%contentWidth]))
+ {
+ Log.ErrorFormat(Resources.TableViewPasteController_PasteCellsToRow_Can_not_paste_value_into_cell_0_1_Row_0_will_be_skipped,
+ startRowIndex, startColumnIndex + i);
+ if (addNewRow)
+ {
+ TableView.SelectRow(index);
+ TableView.DeleteCurrentSelection();
+ }
+ return -1;
+ }
+ }
+ UpdatePastedBlocks(startColumnIndex, pasteWidth, index);
+ }
+ else
+ {
+ var contentWidth = content.Length;
+ var values = new List();
+ for (var i = 0; i < pasteWidth; i++)
+ {
+ values.Add(content[i%contentWidth]);
+ }
+ if (!SafeSetRowCellValues(index, startColumnIndex, values))
+ {
+ Log.ErrorFormat(Resources.TableViewPasteController_PasteCellsToRow_Skipping_invalid_row_0_from_pasting,
+ startRowIndex);
+ if (addNewRow)
+ {
+ TableView.SelectRow(index);
+ TableView.DeleteCurrentSelection();
+ }
+ return -1;
+ }
+ PastedRows.Add(index);
+ }
+ }
+ catch (Exception e)
+ {
+ Log.ErrorFormat(Resources.TableViewPasteController_PasteCellsToRow_Pasting_values_failed_0_, e.Message);
+ }
+ finally
+ {
+ TableView.ExceptionMode = exceptionMode;
+ }
+ return index;
+ }
+
+ protected static string[] SplitToCells(string p)
+ {
+ //tab delimited data: excel, and xtragrid copy (todo think about how to implement pasting of space delimited data)
+ return p.Split(new[]
+ {
+ "\t"
+ }, StringSplitOptions.None);
+ }
+
+ private List PastedRows { get; set; }
+
+ private string[] RemoveHeaderIfPresent(string[] lines)
+ {
+ if (lines.Length > 0 && string.Equals(lines[0], GetTableHeaderString()))
+ {
+ return lines.Skip(1).ToArray(); //skip header
+ }
+ return lines;
+ }
+
+ private string GetTableHeaderString()
+ {
+ //The function xtragrid uses to get the header string is protected and uses dxColumn.GetTextCaption(),
+ //which may differ from dxColumn.GetCaption we use. In those cases this may break. Also if the ordering
+ //of columns is out of sync (can that happen?)
+ return String.Join("\t", TableView.Columns.Where(c => c.Visible).Select(c => c.Caption).ToArray());
+ }
+
+ private void OnPasteFailed(string message)
+ {
+ Log.Warn(message);
+
+ if (PasteFailed != null)
+ {
+ PasteFailed(this, new EventArgs(message));
+ }
+ }
+
+ private void OnPasteFinished()
+ {
+ if (PasteFinished != null)
+ {
+ PasteFinished(this, new EventArgs());
+ }
+ }
+
+ private void PasteValuesCore(string[] clipboardLines, RectangleSelection targetSelection, bool allowNewRows)
+ {
+ var startRowIndex = targetSelection.Top;
+ var startColumnIndex = targetSelection.Left;
+ if (startRowIndex < 0)
+ {
+ throw new ArgumentException(string.Format(Resources.TableViewPasteController_PasteValuesCore_Invalid_row_number_0_, startRowIndex),
+ "targetSelection");
+ }
+
+ //paste all the lines once...
+ int lastRowIndex = Math.Max(startRowIndex + clipboardLines.Length - 1, targetSelection.Bottom);
+
+ int currentClipBoardLineIndex = 0;
+ int canceledNewRows = 0;
+ for (int j = startRowIndex; j <= lastRowIndex; j++)
+ {
+ string[] cols = SplitToCells(clipboardLines[currentClipBoardLineIndex]);
+ //Simply set values as text.
+ var pasteWidth = Math.Max(cols.Length, targetSelection.Right - targetSelection.Left + 1);
+ //paste cannot be wider than tablewidth - startColumnIndex
+ pasteWidth = Math.Min(pasteWidth, TableView.Columns.Count(c => c.Visible) - startColumnIndex);
+
+ //do the pasting
+ bool checkCells = (PasteBehaviour == TableViewPasteBehaviourOptions.SkipRowWhenValueIsInvalid);
+ bool addNewRow = allowNewRows && (j >= TableView.RowCount);
+ var pasteStartRowIndex = j - canceledNewRows;
+
+ var pasteResult = PasteCellsToRow(cols, pasteStartRowIndex, startColumnIndex, pasteWidth, addNewRow,
+ checkCells);
+
+ if (addNewRow && pasteResult == -1)
+ {
+ canceledNewRows++;
+ }
+
+ //update clipboard line index..loop
+ currentClipBoardLineIndex++;
+ if (currentClipBoardLineIndex == clipboardLines.Length)
+ {
+ //break;//do really want repeat data like below?
+ currentClipBoardLineIndex = 0;
+ }
+ }
+ }
+
+ private bool SafeSetRowCellValues(int index, int startColumnIndex, List values)
+ {
+ try
+ {
+ return TableView.SetRowCellValues(index, startColumnIndex, values.ToArray());
+ }
+ catch (Exception e)
+ {
+ Log.ErrorFormat(Resources.TableViewPasteController_SafeSetCellValue_Invalid_row_reason_0_, e.Message);
+ return false;
+ }
+ }
+
+ private bool SafeSetCellValue(int index, int columnIndex, string value)
+ {
+ try
+ {
+ return TableView.SetCellValue(index, columnIndex, value);
+ }
+ catch (Exception e)
+ {
+ Log.ErrorFormat(Resources.TableViewPasteController_SafeSetCellValue_Invalid_row_reason_0_, e.Message);
+ return false;
+ }
+ }
+
+ private void UpdatePastedBlocks(int startColumnIndex, int pasteWidth, int index)
+ {
+ var topLeftCell = new TableViewCell(index, TableView.GetColumnByDisplayIndex(startColumnIndex));
+ var bottomRightCell = new TableViewCell(index, TableView.GetColumnByDisplayIndex(startColumnIndex + pasteWidth - 1));
+ if (PastedBlocks.Count == 0)
+ {
+ PastedBlocks.Add(new RectangleSelection(topLeftCell, bottomRightCell));
+ }
+ else
+ {
+ // if we can extend a rectangular block, do it...
+ var selectBlock = PastedBlocks.Where(b => b.Bottom + 1 == index);
+ if (selectBlock.Any())
+ {
+ selectBlock.First().Bottom++;
+ }
+ else
+ {
+ PastedBlocks.Add(new RectangleSelection(topLeftCell, bottomRightCell));
+ }
+ }
+ }
+
+ private void SetSelection()
+ {
+ if (PastedRows.Count != 0)
+ {
+ TableView.ClearSelection();
+ TableView.SelectRows(PastedRows.ToArray());
+ }
+
+ if (PastedBlocks.Count != 0)
+ {
+ TableView.ClearSelection();
+ foreach (var selection in PastedBlocks)
+ {
+ TableView.SelectCells(selection.Top, selection.Left, selection.Bottom, selection.Right, false);
+ }
+ }
+ }
+
+ private static string[] GetClipboardLines()
+ {
+ var strPasteText = Clipboard.GetText();
+ var lines = strPasteText.Split(new[]
+ {
+ "\r\n"
+ }, StringSplitOptions.None);
+ return RemoveLastLineIfEmpty(lines);
+ }
+
+ private static string[] RemoveLastLineIfEmpty(string[] lines)
+ {
+ if (lines[lines.Length - 1] == "")
+ {
+ return lines.ToList().Take(lines.Length - 1).ToArray();
+ }
+ return lines;
+ }
+
+ ///
+ /// Rectangular selection on a tableview.
+ ///
+ protected class RectangleSelection
+ {
+ public RectangleSelection(TableViewCell topLeft, TableViewCell bottomRight)
+ {
+ Top = topLeft.RowIndex;
+ Left = topLeft.Column == null ? 0 : topLeft.Column.DisplayIndex;
+ Bottom = bottomRight.RowIndex;
+ Right = bottomRight.Column == null ? 0 : bottomRight.Column.DisplayIndex;
+ }
+
+ public int Top { get; set; }
+
+ public int Left { get; set; }
+
+ public int Bottom { get; set; }
+
+ public int Right { get; set; }
+ }
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/Validation/RowValidationResult.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/Validation/RowValidationResult.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/Validation/RowValidationResult.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,23 @@
+using System;
+
+namespace Core.Common.Controls.Table.Validation
+{
+ public class RowValidationResult
+ {
+ public RowValidationResult(string errorText) : this(-1, errorText) //-1 = no specific column, row error
+ {}
+
+ public RowValidationResult(int columnIndex, string errorText)
+ {
+ ColumnIndex = columnIndex;
+ ErrorText = errorText;
+ Valid = String.IsNullOrEmpty(ErrorText);
+ }
+
+ public int ColumnIndex { get; private set; }
+
+ public string ErrorText { get; private set; }
+
+ public bool Valid { get; private set; }
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/Validation/TableViewValidator.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/Validation/TableViewValidator.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/Validation/TableViewValidator.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,172 @@
+using System;
+using System.Linq;
+using Core.Common.Controls.Table.Properties;
+using DevExpress.XtraEditors.Controls;
+using DevExpress.XtraGrid.Views.Base;
+using DevExpress.XtraGrid.Views.Grid;
+
+namespace Core.Common.Controls.Table.Validation
+{
+ public class TableViewValidator
+ {
+ private readonly TableView tableView;
+
+ private object[] originalRowValues;
+ private bool editingRow;
+ private int currentRowIndex;
+
+ public TableViewValidator(TableView tableView)
+ {
+ this.tableView = tableView;
+ AutoValidation = true;
+ }
+
+ public bool ValidateRow(int rowIndex, out string firstError)
+ {
+ firstError = "";
+ BeginEditRow(rowIndex);
+
+ if (tableView.RowValidator != null)
+ {
+ //clear all errors first
+ foreach (var column in tableView.Columns)
+ {
+ tableView.SetColumnError(column, "");
+ }
+
+ tableView.SetColumnError(null, ""); //clear row error
+
+ var result = tableView.RowValidator(rowIndex, GetRowValues());
+
+ if (!result.Valid)
+ {
+ firstError = string.Format(Resources.TableViewValidator_ValidateRow_Validation_of_row_failed_0_, result.ErrorText);
+ tableView.SetColumnError(result.ColumnIndex == -1 ? null : tableView.Columns[result.ColumnIndex],
+ result.ErrorText);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public bool ValidateCell(TableViewCell cell, object newValue, out string error)
+ {
+ BeginEditRow(cell.RowIndex);
+
+ error = "";
+
+ if (tableView.InputValidator != null)
+ {
+ var result = tableView.InputValidator(cell, newValue);
+ if (!result.Item2)
+ {
+ error = string.Format(Resources.TableViewValidator_ValidateCell_Validation_of_cell_failed_0_, result.Item1);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void RefreshRowData()
+ {
+ EndEditRow();
+ }
+
+ private void BeginEditRow(int rowIndex)
+ {
+ if (currentRowIndex >= 0 && rowIndex != currentRowIndex)
+ {
+ EndEditRow();
+ }
+
+ if (editingRow)
+ {
+ return;
+ }
+
+ currentRowIndex = rowIndex;
+
+ editingRow = true;
+
+ originalRowValues = GetRowValues();
+ }
+
+ private object[] GetRowValues()
+ {
+ return tableView.Columns
+ .Where(column => column.Visible)
+ .Select(c => tableView.GetCellValue(currentRowIndex, c.AbsoluteIndex))
+ .ToArray();
+ }
+
+ private void EndEditRow()
+ {
+ if (!editingRow)
+ {
+ return;
+ }
+
+ editingRow = false;
+ currentRowIndex = -1;
+ originalRowValues = null;
+ }
+
+ private object[] GetOriginalRowValues()
+ {
+ if (editingRow)
+ {
+ return originalRowValues;
+ }
+
+ return GetRowValues(); //otherwise just get the values directly
+ }
+
+ #region Event Handlers
+
+ public void RowLostFocus(object sender, FocusedRowChangedEventArgs e)
+ {
+ if (e.FocusedRowHandle != int.MinValue && e.FocusedRowHandle != currentRowIndex)
+ {
+ EndEditRow();
+ }
+ }
+
+ public bool AutoValidation { get; set; }
+
+ public void OnCellValueChanged(object sender, CellValueChangedEventArgs e) //after cell value changed, check the entire row
+ {
+ if (AutoValidation)
+ {
+ string error;
+ ValidateRow(e.RowHandle, out error);
+ }
+ }
+
+ public void OnValidateCell(TableViewCell cell, BaseContainerValidateEditorEventArgs e) //before cell value changed
+ {
+ string error;
+ e.Valid = ValidateCell(cell, e.Value, out error);
+ e.ErrorText = error;
+
+ tableView.SetColumnError(cell.Column, error);
+ }
+
+ public void OnValidateRow(object sender, ValidateRowEventArgs e) //all values might have changed, do a full validation
+ {
+ string error;
+ e.Valid = ValidateRow(e.RowHandle, out error);
+ }
+
+ public void HiddenEditor(object sender, EventArgs e)
+ {
+ var view = sender as GridView;
+ if (view != null)
+ {
+ view.ClearColumnErrors();
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/WizardDialog.Designer.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/WizardDialog.Designer.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/WizardDialog.Designer.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,119 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace Core.Common.Controls.Table
+{
+ partial class WizardDialog
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ private Timer updateButtonsTimer = new Timer();
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ KeyUp -= OnPageModified;
+
+ if (disposing && (updateButtonsTimer != null))
+ {
+ updateButtonsTimer.Dispose();
+ }
+
+ if (disposing && (components != null))
+ {
+ foreach (var wizardPage in wizardPages.OfType())
+ {
+ wizardPage.Dispose();
+ }
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WizardDialog));
+ this.wizardControl1 = new DevExpress.XtraWizard.WizardControl();
+ this.welcomeWizardPage1 = new DevExpress.XtraWizard.WelcomeWizardPage();
+ this.richTextBoxWelcome = new System.Windows.Forms.RichTextBox();
+ this.completionWizardPage1 = new DevExpress.XtraWizard.CompletionWizardPage();
+ this.richTextBoxFinished = new System.Windows.Forms.RichTextBox();
+ ((System.ComponentModel.ISupportInitialize)(this.wizardControl1)).BeginInit();
+ this.wizardControl1.SuspendLayout();
+ this.welcomeWizardPage1.SuspendLayout();
+ this.completionWizardPage1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // wizardControl1
+ //
+ this.wizardControl1.Controls.Add(this.welcomeWizardPage1);
+ this.wizardControl1.Controls.Add(this.completionWizardPage1);
+ this.wizardControl1.LookAndFeel.UseDefaultLookAndFeel = false;
+ this.wizardControl1.LookAndFeel.UseWindowsXPTheme = true;
+ this.wizardControl1.Name = "wizardControl1";
+ this.wizardControl1.Pages.AddRange(new DevExpress.XtraWizard.BaseWizardPage[] {
+ this.welcomeWizardPage1,
+ this.completionWizardPage1});
+ //
+ // welcomeWizardPage1
+ //
+ this.welcomeWizardPage1.Controls.Add(this.richTextBoxWelcome);
+ this.welcomeWizardPage1.Name = "welcomeWizardPage1";
+ resources.ApplyResources(this.welcomeWizardPage1, "welcomeWizardPage1");
+ //
+ // richTextBoxWelcome
+ //
+ this.richTextBoxWelcome.BackColor = System.Drawing.SystemColors.Window;
+ this.richTextBoxWelcome.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ resources.ApplyResources(this.richTextBoxWelcome, "richTextBoxWelcome");
+ this.richTextBoxWelcome.Name = "richTextBoxWelcome";
+ this.richTextBoxWelcome.ReadOnly = true;
+ //
+ // completionWizardPage1
+ //
+ this.completionWizardPage1.Controls.Add(this.richTextBoxFinished);
+ this.completionWizardPage1.Name = "completionWizardPage1";
+ resources.ApplyResources(this.completionWizardPage1, "completionWizardPage1");
+ //
+ // richTextBoxFinished
+ //
+ this.richTextBoxFinished.BackColor = System.Drawing.SystemColors.Window;
+ this.richTextBoxFinished.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ resources.ApplyResources(this.richTextBoxFinished, "richTextBoxFinished");
+ this.richTextBoxFinished.Name = "richTextBoxFinished";
+ this.richTextBoxFinished.ReadOnly = true;
+ //
+ // WizardDialog
+ //
+ resources.ApplyResources(this, "$this");
+ this.Controls.Add(this.wizardControl1);
+ this.Name = "WizardDialog";
+ ((System.ComponentModel.ISupportInitialize)(this.wizardControl1)).EndInit();
+ this.wizardControl1.ResumeLayout(false);
+ this.welcomeWizardPage1.ResumeLayout(false);
+ this.completionWizardPage1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ protected DevExpress.XtraWizard.WizardControl wizardControl1;
+ private DevExpress.XtraWizard.WelcomeWizardPage welcomeWizardPage1;
+ private DevExpress.XtraWizard.CompletionWizardPage completionWizardPage1;
+ private System.Windows.Forms.RichTextBox richTextBoxWelcome;
+ private System.Windows.Forms.RichTextBox richTextBoxFinished;
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/WizardDialog.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/WizardDialog.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/WizardDialog.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,367 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using Core.Common.Controls.Dialogs;
+using Core.Common.Controls.Table.Properties;
+using Core.Common.Controls.Views;
+using DevExpress.XtraWizard;
+
+namespace Core.Common.Controls.Table
+{
+ public partial class WizardDialog : DialogBase, IView
+ {
+ private readonly IList pages;
+ private readonly IDictionary wizardPages = new Dictionary();
+
+ public WizardDialog(IWin32Window owner, Icon icon) : base(owner, icon, 450, 300)
+ {
+ pages = new List();
+ InitializeComponent();
+ wizardControl1.SelectedPageChanged += WizardControl1SelectedPageChanged;
+ wizardControl1.SelectedPageChanging += WizardControl1SelectedPageChanging;
+ wizardControl1.FinishClick += WizardControl1FinishClick;
+ wizardControl1.CancelClick += WizardControl1CancelClick;
+ wizardControl1.NextClick += WizardControl1NextClick;
+ wizardControl1.PrevClick += WizardControl1PrevClick;
+
+ KeyPreview = true; //catch key events in pages
+ KeyUp += OnPageModified;
+
+ updateButtonsTimer.Interval = 300;
+ updateButtonsTimer.Tick += UpdateNavigationButtonsTimerTick;
+ }
+
+ public virtual object Data { get; set; }
+
+ public IEnumerable Pages
+ {
+ get
+ {
+ return pages;
+ }
+ }
+
+ public IList PageTitles
+ {
+ get
+ {
+ return Enumerable.OfType(wizardControl1.Pages).Select(p => p.Text).ToList();
+ }
+ }
+
+ public IList PageDescriptions
+ {
+ get
+ {
+ return Enumerable.OfType(wizardControl1.Pages).Select(p => p.DescriptionText).ToList();
+ }
+ }
+
+ public IComponent CurrentPage
+ {
+ get
+ {
+ if ((wizardControl1.SelectedPageIndex == 0) ||
+ (wizardControl1.SelectedPageIndex == wizardControl1.Pages.Count - 1))
+ {
+ return wizardControl1.Pages[wizardControl1.SelectedPageIndex];
+ }
+ return pages[wizardControl1.SelectedPageIndex - 1];
+ }
+ set
+ {
+ wizardControl1.SelectedPageIndex = pages.IndexOf(value) + 1;
+ }
+ }
+
+ public string WelcomeMessage
+ {
+ get
+ {
+ return welcomeWizardPage1.IntroductionText;
+ }
+ set
+ {
+ welcomeWizardPage1.IntroductionText = value;
+ richTextBoxWelcome.Text = value;
+ }
+ }
+
+ public string FinishedPageMessage
+ {
+ get
+ {
+ return completionWizardPage1.FinishText;
+ }
+ set
+ {
+ completionWizardPage1.FinishText = value;
+ richTextBoxFinished.Text = value;
+ }
+ }
+
+ public string Title
+ {
+ get
+ {
+ return wizardControl1.Text;
+ }
+ set
+ {
+ wizardControl1.Text = value;
+ }
+ }
+
+ public virtual void UpdateNavigationButtons()
+ {
+ if (!(CurrentPage is IWizardPage) || wizardPages == null || !wizardPages.ContainsKey(CurrentPage))
+ {
+ return;
+ }
+
+ var wizardPage = CurrentPage as IWizardPage;
+ var containerPage = wizardPages[CurrentPage];
+
+ if (containerPage != null)
+ {
+ containerPage.AllowBack = wizardPage.CanDoPrevious();
+ containerPage.AllowNext = wizardPage.CanDoNext();
+ }
+ }
+
+ public void AddPage(IComponent page, string title, string description)
+ {
+ var pageControl = (Control) page;
+ pageControl.Dock = DockStyle.Fill;
+
+ var wizardPage = new WizardPage
+ {
+ Text = title, DescriptionText = description, Dock = DockStyle.Fill
+ };
+ wizardPage.Controls.Add(pageControl);
+
+ wizardControl1.Controls.Add(wizardPage);
+ wizardControl1.Pages.Insert(wizardControl1.Pages.Count - 1, wizardPage);
+
+ wizardPages[page] = wizardPage;
+ pages.Add(page);
+ }
+
+ public void RemovePage(IComponent page)
+ {
+ var wizardPage = wizardControl1.Controls.OfType().FirstOrDefault(p => p.Controls.Contains((Control) page));
+ if (wizardPage == null)
+ {
+ return;
+ }
+
+ wizardControl1.Controls.Remove(wizardPage);
+ wizardControl1.Pages.Remove(wizardPage);
+
+ wizardPages.Remove(page);
+ pages.Remove(page);
+ }
+
+ public DialogResult ShowModal()
+ {
+ if (ShowDialog() == DialogResult.OK)
+ {
+ return DialogResult.OK;
+ }
+ return DialogResult.Cancel;
+ }
+
+ protected bool WelcomePageVisible
+ {
+ set
+ {
+ welcomeWizardPage1.Visible = value;
+ }
+ }
+
+ protected bool CompletionPageVisible
+ {
+ set
+ {
+ completionWizardPage1.Visible = value;
+ }
+ }
+
+ protected virtual void OnPageReverted(IWizardPage page) {}
+
+ protected virtual void OnPageCompleted(IWizardPage page) {}
+
+ protected virtual void OnDialogFinished() {}
+
+ ///
+ /// Override this method if you want to choose the next page on basis of choices that were made in one of the pages
+ /// The direction is forward
+ ///
+ /// The index of the page you are leaving
+ /// The next page index, -1 if the default is used
+ protected virtual int FindNextPageIndexMovingForward(int previousPageIndex)
+ {
+ return -1;
+ }
+
+ ///
+ /// Override this method if you want to choose the next page on basis of choices that were made in one of the pages
+ /// The direction is backward
+ ///
+ /// The index of the page you are leaving
+ /// The next page index, -1 if the default is used
+ protected virtual int FindNextPageIndexMovingBackward(int previousPageIndex)
+ {
+ return -1;
+ }
+
+ protected virtual void WizardControl1SelectedPageChanging(object sender, WizardPageChangingEventArgs e)
+ {
+ var nextPageIndex = EvaluateNextPageIndex(wizardControl1.SelectedPageIndex, e.Direction);
+ if (nextPageIndex > 0)
+ {
+ e.Page = wizardControl1.Pages[nextPageIndex];
+ }
+ }
+
+ private void WizardControl1SelectedPageChanged(object sender, WizardPageChangedEventArgs e)
+ {
+ UpdateNavigationButtons();
+ }
+
+ private void WizardControl1PrevClick(object sender, WizardCommandButtonClickEventArgs e)
+ {
+ if (CurrentPage is IWizardPage)
+ {
+ IWizardPage wizardPage = (IWizardPage) CurrentPage;
+ if (!wizardPage.CanDoPrevious())
+ {
+ // setting handled to true will prevent default handling
+ e.Handled = true;
+ }
+ else
+ {
+ try
+ {
+ OnPageReverted(wizardPage);
+ }
+ catch (Exception ee)
+ {
+ ShowExceptionInMessageWindow(ee);
+ e.Handled = true;
+ }
+ }
+ }
+ }
+
+ private void WizardControl1NextClick(object sender, WizardCommandButtonClickEventArgs e)
+ {
+ if (CurrentPage is IWizardPage)
+ {
+ var wizardPage = (IWizardPage) CurrentPage;
+ if (!wizardPage.CanDoNext())
+ {
+ // setting handled to true will prevent default handling
+ e.Handled = true;
+ }
+ else
+ {
+ try
+ {
+ OnPageCompleted(wizardPage);
+ }
+ catch (Exception ee)
+ {
+ ShowExceptionInMessageWindow(ee);
+ e.Handled = true;
+ }
+ }
+ }
+ }
+
+ private void ShowExceptionInMessageWindow(Exception ee)
+ {
+ var message = string.Format(Resources.WizardDialog_WizardControl1NextClick_An_error_occurred_Please_verify_your_input_Error_0_, ee.Message);
+ MessageBox.Show(message, Resources.WizardDialog_WizardControl1NextClick_Error_occurred, MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ }
+
+ private void WizardControl1CancelClick(object sender, CancelEventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+
+ private void WizardControl1FinishClick(object sender, CancelEventArgs e)
+ {
+ if (CurrentPage is IWizardPage)
+ {
+ IWizardPage wizardPage = (IWizardPage) CurrentPage;
+ if (!wizardPage.CanFinish())
+ {
+ return;
+ }
+ }
+
+ OnDialogFinished();
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+
+ ///
+ /// Sometimes you want hide a page depending on choices in other pages
+ /// Use this method to determine the index of the page you want to go to
+ /// depending on choices that were made and the direction you are moving
+ ///
+ /// The index of the page you are leaving
+ /// Moving forward or backward through the wizard
+ /// The next page index, -1 if the default is used
+ private int EvaluateNextPageIndex(int previousPageIndex, Direction direction)
+ {
+ return (direction == Direction.Forward) ? FindNextPageIndexMovingForward(previousPageIndex) : FindNextPageIndexMovingBackward(previousPageIndex);
+ }
+
+ #region Auto Updates
+
+ private void OnPageModified(object sender, object e)
+ {
+ updateButtonsTimer.Start(); //delayed refresh
+ }
+
+ protected override void WndProc(ref Message m)
+ {
+ const int WM_PARENTNOTIFY = 0x0210;
+ const int WM_SETFOCUS = 0x0007;
+ const int WM_LBUTTONDOWN = 0x0201;
+
+ if (m.Msg == WM_SETFOCUS) //called after child (file) dialog is closed
+ {
+ OnPageModified(null, null);
+ }
+ else if (m.Msg == WM_PARENTNOTIFY)
+ {
+ var subEvent = m.WParam.ToInt32() & 0xFFFF; //LOWORD
+ if (subEvent == WM_LBUTTONDOWN) //called after mouse down anywhere in dialog
+ {
+ OnPageModified(null, null);
+ }
+ }
+ base.WndProc(ref m);
+ }
+
+ private void UpdateNavigationButtonsTimerTick(object sender, EventArgs e)
+ {
+ UpdateNavigationButtons(); //refresh
+ updateButtonsTimer.Stop();
+ }
+
+ #endregion
+
+ protected override Button GetCancelButton()
+ {
+ return null; // Cancel support already implemented by WizardControl
+ }
+ }
+}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/WizardDialog.resx
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/WizardDialog.resx (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/WizardDialog.resx (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,347 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ Fill
+
+
+
+ 0, 0
+
+
+ 493, 345
+
+
+
+ 0
+
+
+ Welkom paginatekst
+
+
+ richTextBoxWelcome
+
+
+ System.Windows.Forms.RichTextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ welcomeWizardPage1
+
+
+ 0
+
+
+ Klik op Volgende om door te gaan.
+
+
+ 493, 345
+
+
+ Welkom bij de wizard.
+
+
+ welcomeWizardPage1
+
+
+ DevExpress.XtraWizard.WelcomeWizardPage, DevExpress.XtraWizard.v9.3, Version=9.3.7.0, Culture=neutral, PublicKeyToken=cef13554f3ca1f2d
+
+
+ wizardControl1
+
+
+ 6
+
+
+ Fill
+
+
+ 0, 0
+
+
+ 493, 345
+
+
+ 2
+
+
+ voltooide paginatekst
+
+
+ richTextBoxFinished
+
+
+ System.Windows.Forms.RichTextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ completionWizardPage1
+
+
+ 0
+
+
+ De wizard is succesvol voltooid.
+
+
+ Klik op Voltooien om deze wizard af te sluiten.
+
+
+ 493, 345
+
+
+ Voltooien van de wizard.
+
+
+ completionWizardPage1
+
+
+ DevExpress.XtraWizard.CompletionWizardPage, DevExpress.XtraWizard.v9.3, Version=9.3.7.0, Culture=neutral, PublicKeyToken=cef13554f3ca1f2d
+
+
+ wizardControl1
+
+
+ 7
+
+
+ wizardControl1
+
+
+ DevExpress.XtraWizard.WizardControl, DevExpress.XtraWizard.v9.3, Version=9.3.7.0, Culture=neutral, PublicKeyToken=cef13554f3ca1f2d
+
+
+ $this
+
+
+ 0
+
+
+ True
+
+
+ 710, 478
+
+
+
+ AAABAAIAICAAAAEAIACoEAAAJgAAABAQAAABACAAaAQAAM4QAAAoAAAAIAAAAEAAAAABACAAAAAAAIAQ
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAJBQEBBAIABQAAAAkAAAALAAAACgEAAAgDAQAEBQMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAIBMIAg0HAw4AAAAeAAAAKQAAAC4AAAAwAAAALwAAACYBAAAZBgMBDAkFAQMAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAqGAoIRyoTR2U8HJR0RiHCdkchznRGIMtqQB66Ti4VlSEUCWEEAgE4AQAAIQcD
+ AQ8LBgIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABNLhQKXzgYI2c/HDpwRB9PfkwjcY1VKKmYXCvhl1wr9HZH
+ Iso2IQ99DAcCQAQDAB0MBwIKDQcCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhlElBINQ
+ JSGMVSh4ml4t2JheLPJuQyC/LBsMawgFAS4LBwIPEQkEAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ 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
+
+
+
+ NoControl
+
+
+ CenterParent
+
+
+ WizardDialog
+
+
+ System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
Index: Core/Common/src/Core.Common.Controls.Table/XtraGridRepositoryItemBuilder.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Controls.Table/XtraGridRepositoryItemBuilder.cs (revision 0)
+++ Core/Common/src/Core.Common.Controls.Table/XtraGridRepositoryItemBuilder.cs (revision 46f5191a65faec434930a191e65f4c23d9ff8cfe)
@@ -0,0 +1,257 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using Core.Common.Controls.Table.Editors;
+using DevExpress.Utils;
+using DevExpress.XtraEditors;
+using DevExpress.XtraEditors.Controls;
+using DevExpress.XtraEditors.Repository;
+using DevExpress.XtraGrid;
+using DevExpress.XtraGrid.Columns;
+using log4net;
+
+namespace Core.Common.Controls.Table
+{
+ public static class XtraGridRepositoryItemBuilder
+ {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(TableViewColumn));
+
+ public static RepositoryItem CreateFromTypeEditor(Editors.ITypeEditor typeEditor, GridControl gridControl, GridColumn column, string caption)
+ {
+ if (typeEditor is MultiLineTextEdior)
+ {
+ // do not use wordwrap
+ column.AppearanceCell.Options.UseTextOptions = true;
+ column.AppearanceCell.TextOptions.WordWrap = WordWrap.NoWrap;
+ column.AppearanceCell.TextOptions.Trimming = Trimming.EllipsisWord;
+
+ return new RepositoryItemMemoEdit
+ {
+ WordWrap = false
+ };
+ }
+
+ var comboBoxTypeEditor = typeEditor as ComboBoxTypeEditor;
+ if (comboBoxTypeEditor != null)
+ {
+ return CreateComboBoxRepositoryItem(comboBoxTypeEditor, gridControl, caption);
+ }
+
+ var buttonEditor = typeEditor as ButtonTypeEditor;
+ if (buttonEditor != null)
+ {
+ var buttonTypeEditorRepositoryItem = new RepositoryItemButtonEdit
+ {
+ TextEditStyle = TextEditStyles.HideTextEditor
+ };
+ var editorButton = buttonTypeEditorRepositoryItem.Buttons[0];
+
+ editorButton.ToolTip = buttonEditor.Tooltip;
+
+ if (buttonEditor.Caption != null || buttonEditor.Image != null)
+ {
+ editorButton.Kind = ButtonPredefines.Glyph;
+ editorButton.Caption = buttonEditor.Caption;
+ editorButton.Image = buttonEditor.Image;
+ }
+
+ buttonTypeEditorRepositoryItem.ButtonClick += (s, e) => ButtonTypeEditorRepositoryItemButtonClick(e, typeEditor);
+ return buttonTypeEditorRepositoryItem;
+ }
+
+ // the mechanisms for validating do not work as expected; perhaps some of the encapsulating layers
+ // consumes events?
+ var repositoryItem = new RepositoryItemPopupContainerEdit
+ {
+ CloseOnOuterMouseClick = false
+ };
+
+ var popupControl = new PopupContainerControl
+ {
+ AutoSize = true
+ };
+ var editorControl = (Control) typeEditor;
+ popupControl.Controls.Add(editorControl);
+
+ repositoryItem.PopupControl = popupControl;
+
+ repositoryItem.QueryPopUp += RepositoryItemQueryPopUp;
+ repositoryItem.QueryResultValue += RepositoryItemQueryResultValue;
+ repositoryItem.Validating += RepositoryItemValidating;
+
+ repositoryItem.CloseUp += (sender, e) => RepositoryItemCloseUp(e, typeEditor);
+ //close and open with enter
+ repositoryItem.CloseUpKey = new KeyShortcut(Keys.Enter);
+
+ return repositoryItem;
+ }
+
+ ///
+ /// Creates a ComboBox editor as . The requested width for rendering
+ /// is determined by the rendersize of the largest string in the selection set or the caption.
+ ///
+ /// It has been assumed the final caption is already set before calling this function.
+ private static RepositoryItem CreateComboBoxRepositoryItem(ComboBoxTypeEditor comboBoxEditor, GridControl dxGridControl, string caption)
+ {
+ RepositoryItem comboBoxRepositoryItem;
+
+ // TODO: make it check if Items is evented, if yes - refresh
+ var items = comboBoxEditor.Items.Cast