change UI to UI.WinForms
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
//using System.Linq;
|
||||
using Telerik.WinControls;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Controls.RadValidationProvider;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represent a base for RadValidation
|
||||
/// </summary>
|
||||
public interface IRadValidationRuleEx
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Represents the List of Controls that belongs to this Rule.
|
||||
/// </summary>
|
||||
List<Control> Controls { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ToolTip Text.
|
||||
/// </summary>
|
||||
string ToolTipText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets ToolTip Title.
|
||||
/// </summary>
|
||||
string ToolTipTitle { get; set; }
|
||||
/// <summary>
|
||||
/// Enable ot disable the ToolTip showing when validation fails.
|
||||
/// </summary>
|
||||
bool AutoToolTip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the Rule Expression e.g. 'Value > 5'
|
||||
/// </summary>
|
||||
string Expression { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets or sets the PropertyName which will be evaluated. For example 'Value' Property.
|
||||
/// </summary>
|
||||
string PropertyName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Add a RadControl descendant to the Rule's Controls collection.
|
||||
/// </summary>
|
||||
/// <param name="control">RadControl descendant instance</param>
|
||||
void AddControl(RadControl control);
|
||||
|
||||
/// <summary>
|
||||
/// Remove a RadControl descendant from the Rule's Controls collection.
|
||||
/// </summary>
|
||||
/// <param name="control">RadControl descendant instance</param>
|
||||
void RemoveControl(RadControl control);
|
||||
string ToString();
|
||||
|
||||
/// <summary>
|
||||
/// The Value of the rule. This Value will be evaluated against the Property.
|
||||
/// </summary>
|
||||
object Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Turn On or Off the CaseSensitive evaluation.
|
||||
/// </summary>
|
||||
bool CaseSensitive { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
using System.ComponentModel;
|
||||
using System.Drawing.Design;
|
||||
using Telerik.WinControls;
|
||||
|
||||
//using System.Linq;
|
||||
using Telerik.WinControls.Data;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Controls.RadValidationProvider;
|
||||
|
||||
/// <summary>
|
||||
/// RadCompositeValidationRule evaluates two or more RadValidationRules or RadValidationRuleWithTargetControl
|
||||
/// and combines their with AND or OR operator.
|
||||
/// </summary>
|
||||
public class RadCompositeValidationRuleEx : CompositeFilterDescriptor, IRadValidationRuleEx
|
||||
{
|
||||
private bool caseSensitive = false;
|
||||
private string toolTipText = "";
|
||||
private string toolTipTitle = "Validation Failed";
|
||||
private bool autoToolTip = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets a collection with RadControl descendants that belongs this Rule.
|
||||
/// </summary>
|
||||
[Editor(DesignerConsts.RadValidationRuleAssociatedControlsEditorString, typeof(UITypeEditor))]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public List<Control> Controls
|
||||
{
|
||||
get
|
||||
{
|
||||
List<Control> controls = [];
|
||||
foreach (IRadValidationRuleEx validationRule in ValidationRules)
|
||||
{
|
||||
foreach (var control in validationRule.Controls)
|
||||
{
|
||||
if (!controls.Contains(control))
|
||||
controls.Add(control);
|
||||
}
|
||||
}
|
||||
|
||||
return controls;
|
||||
}
|
||||
set
|
||||
{
|
||||
foreach (RadControl control in value)
|
||||
{
|
||||
AddControl(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Associates this rule and all controls in ValidationRules collection with the specified RadControl descendant.</para>
|
||||
/// </summary>
|
||||
/// <param name="control">A RadControl descendant that represents the editor.</param>
|
||||
|
||||
public virtual void AddControl(RadControl control)
|
||||
{
|
||||
if (control == null)
|
||||
return;
|
||||
|
||||
foreach (IRadValidationRuleEx validationRule in ValidationRules)
|
||||
{
|
||||
if (!validationRule.Controls.Contains(control))
|
||||
validationRule.AddControl(control);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Removes the specified RadControl descendant from this rule and from all controls in ValidationRules collection .</para>
|
||||
/// </summary>
|
||||
/// <param name="control">A RadControl descendant that represents the editor.</param>
|
||||
public void RemoveControl(RadControl control)
|
||||
{
|
||||
if (control == null)
|
||||
return;
|
||||
|
||||
foreach (IRadValidationRuleEx validationRule in ValidationRules)
|
||||
{
|
||||
while (validationRule.Controls.Contains(control))
|
||||
{
|
||||
validationRule.RemoveControl(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Inherit property. Not used in RadCompositeValidationRule.
|
||||
/// </summary>
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
[Browsable(false)]
|
||||
public override FilterDescriptorCollection FilterDescriptors { get { return base.FilterDescriptors; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the collection of ValidationRules that belongs to this RadValidationProvider.
|
||||
/// </summary>
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
|
||||
Editor(DesignerConsts.RadValidationProviderCompositeConditionsCollectionEditorString, typeof(UITypeEditor)),
|
||||
Category(RadDesignCategory.DataCategory),
|
||||
Description("Gets a collection representing the Rules in this CompositeValidationRule.")]
|
||||
public FilterDescriptorCollection ValidationRules
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.FilterDescriptors;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Rule expression.
|
||||
/// </summary>
|
||||
/// <value>The Rule expression.</value>
|
||||
public override string Expression { get { return base.Expression; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the ToolTip Text.
|
||||
/// </summary>
|
||||
[DefaultValue("")]
|
||||
public string ToolTipText { get { return toolTipText; } set { toolTipText = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the ToolTip Title Text. This text will be shown as ToolTip Title text when rule validation fails.
|
||||
/// </summary>
|
||||
[DefaultValue("Validation Failed")]
|
||||
public string ToolTipTitle { get { return toolTipTitle; } set { toolTipTitle = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Inherited property. Not used in the Rule.
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Browsable(false)]
|
||||
public override bool IsFilterEditor
|
||||
{
|
||||
get { return base.IsFilterEditor; }
|
||||
set { base.IsFilterEditor = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable or Disable the ToolTip when validation fails.
|
||||
/// </summary>
|
||||
[DefaultValue(true)]
|
||||
public bool AutoToolTip
|
||||
{
|
||||
get { return autoToolTip; }
|
||||
set { autoToolTip = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inherited property. Not used in the Rule.
|
||||
/// </summary>
|
||||
[Browsable(false)]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public override object Value { get { return base.Value; } set { base.Value = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Enable or Disable the case sensitive Rule's Like operator.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
public bool CaseSensitive
|
||||
{
|
||||
get
|
||||
{
|
||||
return caseSensitive;
|
||||
}
|
||||
set
|
||||
{
|
||||
caseSensitive = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using Telerik.WinControls;
|
||||
using Telerik.WinControls.UI;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Controls.RadValidationProvider;
|
||||
|
||||
public delegate void RadValidationEventHandlerEx(object sender, RadValidationEventArgsEx e);
|
||||
|
||||
public class RadValidationEventArgsEx : EventArgs
|
||||
{
|
||||
const string DefaultToolTipTitle = "Validation Failed";
|
||||
private readonly Control control;
|
||||
private readonly IRadValidationRuleEx validationRule;
|
||||
private bool displayIconAndToolTip = true;
|
||||
private string errorTitle = DefaultToolTipTitle;
|
||||
private bool enableToolTipShadow = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the ValidationHelperElement descendant that contains the Error image. This element is set next to the validated control.
|
||||
/// </summary>
|
||||
public ValidationHelperElement ValidationHelperElement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the result from the rule evaluation.
|
||||
/// </summary>
|
||||
public bool IsValid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the Control which is evaluated in the ValidationRule.
|
||||
/// </summary>
|
||||
public Control Control { get { return control; } }
|
||||
|
||||
/// <summary>
|
||||
/// Error image that will displayed next to the Validated control.
|
||||
/// </summary>
|
||||
public Image ErrorImage { get; set; }
|
||||
/// <summary>
|
||||
/// Error SVG image that will displayed next to the Validated control.
|
||||
/// </summary>
|
||||
public RadSvgImage ErrorSvgImage { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the custom ToolTip for the Rule.
|
||||
/// </summary>
|
||||
public ToolTip ToolTip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the X position of the ToolTip.
|
||||
/// </summary>
|
||||
public int? ToolTipX { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Y position of the ToolTip.
|
||||
/// </summary>
|
||||
public int? ToolTipY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the ToolTip's duration in Milliseconds
|
||||
/// </summary>
|
||||
public int? ToolTipDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Rule that fires this event.
|
||||
/// </summary>
|
||||
public IRadValidationRuleEx ValidationRule { get { return validationRule; } }
|
||||
|
||||
/// <summary>
|
||||
/// Sets or Gets the ToolTip's Text.
|
||||
/// </summary>
|
||||
public string ErrorText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets or Gets the ToolTip's Title.
|
||||
/// </summary>
|
||||
public string ErrorTitle { get { return errorTitle; } set { errorTitle = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Enable or Disable the Error border and error image.
|
||||
/// </summary>
|
||||
public bool DisplayIconAndToolTip { get { return displayIconAndToolTip; } set { displayIconAndToolTip = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Enable or Disable the ToolTip shadow.
|
||||
/// </summary>
|
||||
public bool EnableToolTipShadow { get { return enableToolTipShadow; } set { enableToolTipShadow = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Construct the RadValidationEventArgs object.
|
||||
/// </summary>
|
||||
/// <param name="control">The validated control. Must be RadEditorControl descendant</param>
|
||||
/// <param name="errorImage">Erorr image</param>
|
||||
/// <param name="errorText">Error text</param>
|
||||
/// <param name="errorTitle">Error title</param>
|
||||
/// <param name="validationRule">Validation rule</param>
|
||||
/// <param name="isFailed">Validatation failed</param>
|
||||
public RadValidationEventArgsEx(
|
||||
Control control,
|
||||
Image errorImage,
|
||||
string errorText,
|
||||
string errorTitle,
|
||||
IRadValidationRuleEx validationRule,
|
||||
bool isFailed)
|
||||
{
|
||||
this.control = control;
|
||||
ErrorImage = errorImage;
|
||||
ErrorText = errorText;
|
||||
this.validationRule = validationRule;
|
||||
IsValid = !isFailed;
|
||||
this.errorTitle = errorTitle;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,732 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing.Design;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Telerik.Data.Expressions;
|
||||
using Telerik.WinControls;
|
||||
using Telerik.WinControls.Data;
|
||||
using Telerik.WinControls.Design;
|
||||
using Telerik.WinControls.UI;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Controls.RadValidationProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a validation management for RadControl descendant editors.
|
||||
/// </summary>
|
||||
[ToolboxItem(true)]
|
||||
[TelerikToolboxCategory(ToolboxGroupStrings.EditorsGroup)]
|
||||
[Designer(DesignerConsts.RadValidationProviderDesignerString)]
|
||||
[ProvideProperty("ValidationRule", typeof(RadControl))]
|
||||
[ProvideProperty("IconAlignment", typeof(RadControl))]
|
||||
[ProvideProperty("IconPadding", typeof(RadControl))]
|
||||
public class RadValidationProviderEx : Component, ISupportInitialize, IExtenderProvider
|
||||
{
|
||||
#region Externs
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetClassLong")]
|
||||
private static extern int GetClassLong(nint hWnd, int nIndex);
|
||||
[DllImport("user32.dll", EntryPoint = "SetClassLong")]
|
||||
private static extern int SetClassLong(nint hWnd, int nIndex, int dwNewLong);
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
private FilterDescriptorCollection validationRules = [];
|
||||
private ValidationMode validationMode = ValidationMode.OnValidating;
|
||||
private Dictionary<RadControl, ErrorIconAlignment> errorIconAlignments = [];
|
||||
private Dictionary<RadControl, Padding> errorIconPadding = [];
|
||||
private Dictionary<RadControl, ToolTip> controlsToToolTips = [];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public bool AllowCancelControlEvents { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before a RadControl is being validated.
|
||||
/// </summary>
|
||||
public event RadValidationEventHandlerEx ControlValidation;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the ValidionMode property changed.
|
||||
/// </summary>
|
||||
public event EventHandler ValidationModeChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the ValidationMode.
|
||||
/// </summary>
|
||||
[DefaultValue(typeof(ValidationMode), "OnValidating")]
|
||||
public ValidationMode ValidationMode
|
||||
{
|
||||
get { return validationMode; }
|
||||
set
|
||||
{
|
||||
if (validationMode != value)
|
||||
{
|
||||
validationMode = value;
|
||||
CallOnValidationChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the collection of ValidationRules that belongs to this RadValidationProvider.
|
||||
/// </summary>
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
|
||||
Editor(DesignerConsts.RadValidationProviderItemCollectionDesignerString, typeof(UITypeEditor)),
|
||||
Category(RadDesignCategory.DataCategory)]
|
||||
[Description("Gets a collection representing the Conditions in this ValidationProvider.")]
|
||||
public FilterDescriptorCollection ValidationRules
|
||||
{
|
||||
get
|
||||
{
|
||||
return validationRules;
|
||||
}
|
||||
set
|
||||
{
|
||||
validationRules = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Cstor
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the RadValidationProvider class.
|
||||
/// </summary>
|
||||
public RadValidationProviderEx()
|
||||
{
|
||||
validationRules.PropertyChanged += ValidationRules_PropertyChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Initializes a new instance of the RadValidationProvider class with the specified container control.</para>
|
||||
/// </summary>
|
||||
/// <param name="container">An object that implements the <see cref="T:System.ComponentModel.IContainer" /> interface, and owns the created object.</param>
|
||||
public RadValidationProviderEx(IContainer container) : this()
|
||||
{
|
||||
container.Add(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
|
||||
/// <summary>
|
||||
/// Remove a specific RadControl from the validation rules.
|
||||
/// </summary>
|
||||
/// <param name="editorControl">A RadControl descendant.</param>
|
||||
public void RemoveControlFromRules(RadControl editorControl)
|
||||
{
|
||||
foreach (IRadValidationRuleEx rule in ValidationRules)
|
||||
{
|
||||
RemoveValidationRule(editorControl, rule);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a validation rule associated with the specified RadControl descendant.
|
||||
/// </summary>
|
||||
/// <param name="editorControl">A RadControl descendant.</param>
|
||||
/// <param name="ruleToRemove">Rule to remove.</param>
|
||||
public void RemoveValidationRule(RadControl editorControl, IRadValidationRuleEx ruleToRemove)
|
||||
{
|
||||
ruleToRemove.RemoveControl(editorControl);
|
||||
}
|
||||
|
||||
public void BeginInit()
|
||||
{
|
||||
}
|
||||
|
||||
public void EndInit()
|
||||
{
|
||||
EnsureEventSubscribe();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates all editors associated with the RadControl.
|
||||
/// </summary>
|
||||
/// <returns>true if all editors has been successfully validated; otherwise false.</returns>
|
||||
public bool ValidateAll()
|
||||
{
|
||||
var valid = true;
|
||||
|
||||
AssociatedControls.ForEach(control =>
|
||||
{
|
||||
if (!Validate(control))
|
||||
valid = false;
|
||||
});
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the specified editor associated with the RadControl.
|
||||
/// </summary>
|
||||
/// <param name="control">A RadControl or descendant that represents the editor to be validated.</param>
|
||||
/// <returns>true if the editor has been successfully validated; otherwise false.</returns>
|
||||
public bool Validate(RadControl control)
|
||||
{
|
||||
return ValidateCore(control, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Sets the alignment of an error icon for the specified control.</para>
|
||||
/// </summary>
|
||||
/// <param name="control">A target RadControl.</param>
|
||||
/// <param name="errorIconAlignment">An <see cref="T:System.Windows.Forms.ErrorIconAlignment" /> value that specifies the alignment to be set for the RadControl.</param>
|
||||
|
||||
public void SetIconAlignment(RadControl control, ErrorIconAlignment errorIconAlignment)
|
||||
{
|
||||
if (!errorIconAlignments.ContainsKey(control))
|
||||
errorIconAlignments.Add(control, errorIconAlignment);
|
||||
else
|
||||
{
|
||||
errorIconAlignments[control] = errorIconAlignment;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Get the alignment of an error icon for the specified RadControl.</para>
|
||||
/// </summary>
|
||||
/// <param name="control">A target control.</param>
|
||||
/// <returns>An <see cref="T:System.Windows.Forms.ErrorIconAlignment" /> value.</returns>
|
||||
[DefaultValue(ErrorIconAlignment.MiddleRight)]
|
||||
public ErrorIconAlignment GetIconAlignment(RadControl control)
|
||||
{
|
||||
if (errorIconAlignments.ContainsKey(control))
|
||||
return errorIconAlignments[control];
|
||||
|
||||
return ErrorIconAlignment.MiddleRight;
|
||||
}
|
||||
|
||||
/// <summary>Sets the amount of extra space to leave between the specified control and the error icon.</summary>
|
||||
/// <param name="control">The <paramref name="control" /> to set the padding for. </param>
|
||||
/// <param name="errorIconPadding">The padding to add between the icon and the <paramref name="control" />. </param>
|
||||
public void SetIconPadding(RadControl control, Padding errorIconPadding)
|
||||
{
|
||||
if (!this.errorIconPadding.ContainsKey(control))
|
||||
this.errorIconPadding.Add(control, errorIconPadding);
|
||||
else
|
||||
{
|
||||
this.errorIconPadding[control] = errorIconPadding;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Returns the amount of extra space to leave next to the error icon.</summary>
|
||||
/// <returns>The padding to leave between the icon and the control. </returns>
|
||||
/// <param name="control">The control to get the padding for. </param>
|
||||
[DefaultValue(typeof(Padding), "1, 1, 1, 1")]
|
||||
public Padding GetIconPadding(RadControl control)
|
||||
{
|
||||
if (errorIconPadding.ContainsKey(control))
|
||||
return errorIconPadding[control];
|
||||
|
||||
return new Padding(1);
|
||||
}
|
||||
protected virtual void OnControlValidation(RadValidationEventArgsEx e)
|
||||
{
|
||||
if (ControlValidation != null)
|
||||
ControlValidation(this, e);
|
||||
}
|
||||
|
||||
private void ValidationRules_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Item[]")
|
||||
EnsureEventSubscribe();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a rules associated with the control.
|
||||
/// </summary>
|
||||
/// <param name="control">A RadControl descendant</param>
|
||||
public void RemoveRules(RadControl control)
|
||||
{
|
||||
for (var i = validationRules.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (((IRadValidationRuleEx)validationRules[i]).Controls.Contains(control))
|
||||
validationRules.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of the controls whose values are validated.
|
||||
/// </summary>
|
||||
[Browsable(false)]
|
||||
public List<RadControl> AssociatedControls
|
||||
{
|
||||
get => [.. ValidationRules.OfType<IRadValidationRuleEx>().SelectMany(n => n.Controls).OfType<RadControl>()];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the visual indication for the validation error.
|
||||
/// </summary>
|
||||
public virtual void ClearErrorStatus()
|
||||
{
|
||||
var controls = AssociatedControls;
|
||||
for (var i = 0; i < controls.Count; i++)
|
||||
{
|
||||
ClearErrorStatus(controls[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the visual indication for the validation error.
|
||||
/// </summary>
|
||||
/// <param name="associatedControl">A RadControl descendant</param>
|
||||
public virtual void ClearErrorStatus(RadControl associatedControl)
|
||||
{
|
||||
var children = associatedControl.RootElement.Children;
|
||||
if (children.Count == 0)
|
||||
return;
|
||||
|
||||
var editorControl = associatedControl;
|
||||
var controlElement = TryFindControlElement(children);//first non ValidationIconElement is a Main Element for the Control.
|
||||
if (controlElement == null)
|
||||
return;
|
||||
|
||||
var border = ValidationHelperElement.GetBorder(children);
|
||||
|
||||
ValidationHelperElement.RestoreBorderColor(border);
|
||||
associatedControl.ElementTree.ApplyThemeToElementTree();
|
||||
for (var i = children.Count - 1; i >= 0; --i)
|
||||
{
|
||||
if (associatedControl.RootElement.Children[i] is ValidationHelperElement)
|
||||
associatedControl.RootElement.Children.RemoveAt(i);
|
||||
}
|
||||
|
||||
controlElement.PositionOffset = new SizeF();
|
||||
controlElement.MaxSize = new Size();
|
||||
associatedControl.RootElement.InvalidateMeasure(true);
|
||||
associatedControl.RootElement.UpdateLayout();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
private void AssociatedControl_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (ValidationMode == ValidationMode.OnTextChange)
|
||||
ValidateCore(sender, e);
|
||||
}
|
||||
|
||||
private void AssociatedControl_Validating(object sender, CancelEventArgs e)
|
||||
{
|
||||
if (ValidationMode == ValidationMode.OnValidating)
|
||||
ValidateCore(sender, e);
|
||||
}
|
||||
|
||||
internal static object GetSubPropertyValue(object control, string fieldName)
|
||||
{
|
||||
var names = fieldName.Split('.');
|
||||
if (names.Length < 2)
|
||||
return control.GetType().GetProperty(fieldName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(control, null);
|
||||
|
||||
var innerValue = control.GetType().GetProperty(names[0], BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(control, null);
|
||||
var index = 1;
|
||||
while (index < names.Length && innerValue != null)
|
||||
{
|
||||
innerValue = innerValue.GetType().GetProperty(names[index], BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(innerValue, null);
|
||||
index++;
|
||||
}
|
||||
|
||||
return innerValue;
|
||||
}
|
||||
|
||||
private bool ValidateCore(object sender, EventArgs e)
|
||||
{
|
||||
var control = sender as Control;
|
||||
|
||||
foreach (IRadValidationRuleEx ruleToEvaluete in ValidationRules)
|
||||
{
|
||||
if (!ruleToEvaluete.Controls.Contains(control))
|
||||
continue;
|
||||
|
||||
var context = new ExpressionContext();
|
||||
context.Clear();
|
||||
var value = GetSubPropertyValue(control, ruleToEvaluete.PropertyName);//control.GetType().GetProperty(ruleToEvaluete.PropertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(control, null);
|
||||
if (value != null && ruleToEvaluete.Value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Fix for 441010
|
||||
// Try to retrieve Culture from the control
|
||||
var cultureInfo = RetrieveCulture(control);
|
||||
value = Convert.ChangeType(value, ruleToEvaluete.Value.GetType(), cultureInfo);
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
|
||||
context.Add(ruleToEvaluete.PropertyName, value);
|
||||
|
||||
if (string.IsNullOrEmpty(ruleToEvaluete.Expression))
|
||||
continue;
|
||||
|
||||
var node = DataUtils.Parse(ruleToEvaluete.Expression, ruleToEvaluete.CaseSensitive);
|
||||
var result = node.Eval(null, context);
|
||||
|
||||
if (result is bool boolResult)
|
||||
{
|
||||
var validationEventArgs = FireValidationEvent(!boolResult, (RadControl)sender, ruleToEvaluete);
|
||||
if (validationEventArgs.DisplayIconAndToolTip)
|
||||
boolResult = AddOrRemoveImage(validationEventArgs, (RadControl)sender, ruleToEvaluete);
|
||||
else
|
||||
{
|
||||
boolResult = validationEventArgs.IsValid;
|
||||
}
|
||||
|
||||
if (AllowCancelControlEvents && e is CancelEventArgs cancelEventArgs)
|
||||
cancelEventArgs.Cancel = !boolResult;
|
||||
|
||||
if (!boolResult)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool AddOrRemoveImage(RadValidationEventArgsEx validationEventArgs, RadControl associatedControl, IRadValidationRuleEx rule)
|
||||
{
|
||||
var children = associatedControl.RootElement.Children;
|
||||
if (children.Count == 0)
|
||||
return true;
|
||||
|
||||
var editorControl = associatedControl;
|
||||
var controlElement = TryFindControlElement(children);//first non ValidationIconElement is a Main Element for the Control.
|
||||
if (controlElement == null)
|
||||
return true;
|
||||
|
||||
var element = validationEventArgs.ValidationHelperElement;
|
||||
var border = ValidationHelperElement.GetBorder(children);
|
||||
|
||||
var truncateSize = false;
|
||||
if (!validationEventArgs.IsValid)
|
||||
{
|
||||
element ??= new ValidationHelperElement();
|
||||
|
||||
if (!children.Contains(element))
|
||||
truncateSize = true;//size of the control should be truncate
|
||||
|
||||
element.ToolTipText = validationEventArgs.ErrorText;
|
||||
element.AutoToolTip = true;
|
||||
element.StretchHorizontally =
|
||||
element.StretchVertically = false;
|
||||
element.Image = validationEventArgs.ErrorImage;
|
||||
element.SvgImage = validationEventArgs.ErrorSvgImage;
|
||||
element.Alignment = ToContentAligment(GetIconAlignment(editorControl));
|
||||
element.Padding = GetIconPadding(editorControl);
|
||||
if (truncateSize)
|
||||
{
|
||||
var elementSize = TelerikDpiHelper.ScaleSizeF(MeasurementControl.ThreadInstance.GetDesiredSize(element, new SizeF(float.MaxValue, float.MaxValue)), controlElement.DpiScaleFactor);
|
||||
var width = (controlElement.Size.Width - elementSize.Width) / controlElement.DpiScaleFactor.Width;
|
||||
controlElement.MaxSize = new Size((int)width, controlElement.MaxSize.Height);
|
||||
|
||||
associatedControl.RootElement.ResetValue(VisualElement.BackColorProperty, ValueResetFlags.Style);
|
||||
if (element.IsRightLocated)
|
||||
children.Add(element);
|
||||
else
|
||||
{
|
||||
controlElement.PositionOffset = new SizeF(elementSize.Width, 0);
|
||||
children.Insert(0, element);
|
||||
}
|
||||
}
|
||||
|
||||
ValidationHelperElement.SetBorderColor(border);
|
||||
if (rule.AutoToolTip)
|
||||
{
|
||||
var toolTipX = validationEventArgs.ToolTipX.HasValue ? validationEventArgs.ToolTipX.Value : 0;
|
||||
var toolTipY = validationEventArgs.ToolTipY.HasValue ? validationEventArgs.ToolTipY.Value : associatedControl.Height + 1;
|
||||
var toolTipDuration = validationEventArgs.ToolTipDuration.HasValue ? validationEventArgs.ToolTipDuration.Value : 2000;
|
||||
|
||||
if (validationEventArgs.ToolTip != null)
|
||||
{
|
||||
associatedControl.Disposed -= AssociatedControl_Disposed;
|
||||
associatedControl.Disposed += AssociatedControl_Disposed;
|
||||
if (controlsToToolTips.ContainsKey(associatedControl))
|
||||
controlsToToolTips[associatedControl] = validationEventArgs.ToolTip;
|
||||
else
|
||||
{
|
||||
controlsToToolTips.Add(associatedControl, validationEventArgs.ToolTip);
|
||||
}
|
||||
|
||||
if (!validationEventArgs.EnableToolTipShadow)
|
||||
ToolTipRemoveShadow(validationEventArgs.ToolTip);
|
||||
validationEventArgs.ToolTip.Show(element.ToolTipText, associatedControl, toolTipX, toolTipY, toolTipDuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowToolTip(associatedControl, element.ToolTipText, validationEventArgs.ErrorTitle, toolTipX, toolTipY, toolTipDuration, validationEventArgs.EnableToolTipShadow);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ValidationHelperElement.RestoreBorderColor(border);
|
||||
associatedControl.ElementTree.ApplyThemeToElementTree();
|
||||
for (var i = children.Count - 1; i >= 0; --i)
|
||||
{
|
||||
if (associatedControl.RootElement.Children[i] is ValidationHelperElement)
|
||||
associatedControl.RootElement.Children.RemoveAt(i);
|
||||
}
|
||||
|
||||
controlElement.PositionOffset = new SizeF();
|
||||
controlElement.MaxSize = new Size();
|
||||
}
|
||||
|
||||
associatedControl.RootElement.InvalidateMeasure(true);
|
||||
associatedControl.RootElement.UpdateLayout();
|
||||
associatedControl.Refresh();
|
||||
return validationEventArgs.IsValid;
|
||||
}
|
||||
|
||||
private void ToolTipRemoveShadow(ToolTip toolTip)
|
||||
{
|
||||
var hwnd = (nint)typeof(ToolTip).GetProperty("Handle",
|
||||
BindingFlags.NonPublic |
|
||||
BindingFlags.Instance).GetValue(toolTip, null);
|
||||
var cs = GetClassLong(hwnd, NativeMethods.GCL_STYLE);
|
||||
if ((cs & NativeMethods.CS_DROPSHADOW) == NativeMethods.CS_DROPSHADOW)
|
||||
{
|
||||
cs &= ~NativeMethods.CS_DROPSHADOW;
|
||||
SetClassLong(hwnd, NativeMethods.GCL_STYLE, cs);
|
||||
}
|
||||
}
|
||||
|
||||
private void AssociatedControl_Disposed(object sender, EventArgs e)
|
||||
{
|
||||
var radControl = sender as RadControl;
|
||||
radControl.Disposed -= AssociatedControl_Disposed;
|
||||
if (radControl != null && controlsToToolTips.ContainsKey(radControl))
|
||||
{
|
||||
var toolTip = controlsToToolTips[radControl];
|
||||
if (toolTip != null)
|
||||
{
|
||||
controlsToToolTips.Remove(radControl);
|
||||
toolTip.Dispose();
|
||||
toolTip = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ShowToolTip(RadControl associatedControl, string toolTipText, string toolTipTitle, int toolTipX, int toolTipY, int toolTipDuration, bool enableToolTipShadow)
|
||||
{
|
||||
var toolTip = new ToolTip
|
||||
{
|
||||
ToolTipTitle = toolTipTitle,
|
||||
|
||||
BackColor = Color.Red,
|
||||
ForeColor = Color.White,
|
||||
OwnerDraw = true,
|
||||
InitialDelay = 0,
|
||||
AutoPopDelay = toolTipDuration
|
||||
};
|
||||
if (!enableToolTipShadow)
|
||||
ToolTipRemoveShadow(toolTip);
|
||||
|
||||
toolTip.Draw += delegate (object sender, DrawToolTipEventArgs e)
|
||||
{
|
||||
e.DrawBackground();
|
||||
e.DrawBorder();
|
||||
using (var brush = new SolidBrush(Color.White))
|
||||
using (var titleFont = new Font("Segoe UI", 8f, FontStyle.Bold))
|
||||
using (var textFont = new Font("Segoe UI", 8f, FontStyle.Regular))
|
||||
{
|
||||
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
|
||||
if (!string.IsNullOrEmpty(toolTipTitle))
|
||||
{
|
||||
e.Graphics.DrawString(toolTipTitle, titleFont, brush, new Point(2, 2));
|
||||
e.Graphics.DrawString(toolTipText, textFont, brush, new Point(2, 19));
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Graphics.DrawString(toolTipText, textFont, brush, new Point(2, 2));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (controlsToToolTips.ContainsKey(associatedControl))
|
||||
controlsToToolTips[associatedControl] = toolTip;
|
||||
else
|
||||
{
|
||||
controlsToToolTips.Add(associatedControl, toolTip);
|
||||
}
|
||||
|
||||
associatedControl.Disposed -= AssociatedControl_Disposed;
|
||||
associatedControl.Disposed += AssociatedControl_Disposed;
|
||||
|
||||
toolTip.Show(toolTipText, associatedControl, toolTipX, toolTipY, toolTipDuration);
|
||||
}
|
||||
|
||||
private ContentAlignment ToContentAligment(ErrorIconAlignment errorIconAlignment)
|
||||
{
|
||||
switch (errorIconAlignment)
|
||||
{
|
||||
case ErrorIconAlignment.TopLeft:
|
||||
return ContentAlignment.TopLeft;
|
||||
case ErrorIconAlignment.TopRight:
|
||||
return ContentAlignment.TopRight;
|
||||
case ErrorIconAlignment.MiddleLeft:
|
||||
return ContentAlignment.MiddleLeft;
|
||||
case ErrorIconAlignment.MiddleRight:
|
||||
return ContentAlignment.MiddleRight;
|
||||
case ErrorIconAlignment.BottomLeft:
|
||||
return ContentAlignment.BottomLeft;
|
||||
case ErrorIconAlignment.BottomRight:
|
||||
return ContentAlignment.BottomRight;
|
||||
default:
|
||||
return ContentAlignment.MiddleRight;
|
||||
}
|
||||
}
|
||||
|
||||
private static RadElement TryFindControlElement(RadElementCollection children)
|
||||
{
|
||||
RadElement controlElement = null;
|
||||
foreach (var child in children)
|
||||
{
|
||||
if (child is not ValidationHelperElement)
|
||||
{
|
||||
controlElement = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return controlElement;
|
||||
}
|
||||
|
||||
protected virtual RadValidationEventArgsEx FireValidationEvent(bool isNotValid, RadControl associatedControl, IRadValidationRuleEx rule)
|
||||
{
|
||||
Image image = ResourceHelper.ImageFromResource(typeof(global::Telerik.WinControls.UI.RadValidationProvider), "Telerik.WinControls.UI.Resources.error-icon.png");
|
||||
var errorText = string.IsNullOrEmpty(rule.ToolTipText) ? rule.Expression : rule.ToolTipText;
|
||||
var validationEventArgs = new RadValidationEventArgsEx(associatedControl, image, errorText, rule.ToolTipTitle, rule, isNotValid)
|
||||
{
|
||||
ValidationHelperElement = ValidationHelperElement.GetValidationElement(associatedControl.RootElement.Children)
|
||||
};
|
||||
validationEventArgs.ValidationHelperElement ??= new ValidationHelperElement();
|
||||
|
||||
OnControlValidation(validationEventArgs);
|
||||
return validationEventArgs;
|
||||
}
|
||||
|
||||
private void EnsureEventSubscribe()
|
||||
{
|
||||
foreach (IRadValidationRuleEx rule in ValidationRules)
|
||||
{
|
||||
var controls = rule.Controls;
|
||||
foreach (var control in controls)
|
||||
{
|
||||
if (control != null)
|
||||
{
|
||||
control.Validating -= AssociatedControl_Validating;
|
||||
control.Validating += AssociatedControl_Validating;
|
||||
control.TextChanged -= AssociatedControl_TextChanged;
|
||||
control.TextChanged += AssociatedControl_TextChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CallOnValidationChanged()
|
||||
{
|
||||
if (ValidationModeChanged != null)
|
||||
ValidationModeChanged(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private CultureInfo RetrieveCulture(Control control)
|
||||
{
|
||||
var cultureProperty = control.GetType().GetProperty("Culture", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
|
||||
if (cultureProperty != null)
|
||||
{
|
||||
var cultureObject = cultureProperty.GetValue(control, null);
|
||||
if (cultureObject != null && cultureObject is CultureInfo)
|
||||
return cultureObject as CultureInfo;
|
||||
}
|
||||
|
||||
return CultureInfo.CurrentCulture;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ExtenderProvider Interface implementation
|
||||
|
||||
/// <summary>
|
||||
/// <para>Indicates whether a control can be extended.</para>
|
||||
/// </summary>
|
||||
/// <param name="extendee">The control to be extended.</param>
|
||||
/// <returns>true if the control can be extended otherwise false.</returns>
|
||||
public bool CanExtend(object extendee)
|
||||
{
|
||||
return extendee is RadControl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Associates a validation rule with the specified RadControl descendant.</para>
|
||||
/// </summary>
|
||||
/// <param name="control">A RadControl descendant that represents the editor.</param>
|
||||
/// <param name="rule">A RadValidationRule descendant that represents the validation rule.</param>
|
||||
[Editor(DesignerConsts.RadValidationRuleEditorString, typeof(UITypeEditor))]
|
||||
public void SetValidationRule(RadControl control, FilterDescriptor rule)
|
||||
{
|
||||
if (rule is not IRadValidationRuleEx radValidationRule)
|
||||
RemoveControlFromRules(control);
|
||||
else
|
||||
{
|
||||
radValidationRule.AddControl(control);
|
||||
if (!validationRules.Contains(rule))
|
||||
validationRules.Add(rule);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Associates a validation rule with the specified RadControls descendant.</para>
|
||||
/// </summary>
|
||||
/// <param name="controls">A RadControl collection descendant that represents the editors.</param>
|
||||
/// <param name="rule">A RadValidationRule descendant that represents the validation rule.</param>
|
||||
[Editor(DesignerConsts.RadValidationRuleEditorString, typeof(UITypeEditor))]
|
||||
public void SetValidationRule(IEnumerable controls, FilterDescriptor rule)
|
||||
{
|
||||
SetValidationRule(controls.OfType<RadControl>(), rule);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Associates a validation rule with the specified RadControls descendant.</para>
|
||||
/// </summary>
|
||||
/// <param name="controls">A RadControl collection descendant that represents the editors.</param>
|
||||
/// <param name="rule">A RadValidationRule descendant that represents the validation rule.</param>
|
||||
[Editor(DesignerConsts.RadValidationRuleEditorString, typeof(UITypeEditor))]
|
||||
public void SetValidationRule(IEnumerable<RadControl> controls, FilterDescriptor rule)
|
||||
{
|
||||
foreach (var control in controls)
|
||||
SetValidationRule(control, rule);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Returns a validation rule associated with the specified RadControl descendant.</para>
|
||||
/// </summary>
|
||||
/// <param name="control">A RadControl descendant.</param>
|
||||
/// <returns>A RadValidationRule descendant that represents the validation rule associated with the editor. Null if no validation rule is associated with the specified control.</returns>
|
||||
|
||||
[Editor(DesignerConsts.RadValidationRuleEditorString, typeof(UITypeEditor))]
|
||||
public FilterDescriptor GetValidationRule(RadControl control)
|
||||
{
|
||||
IRadValidationRuleEx ruleToEvaluete = null;
|
||||
foreach (IRadValidationRuleEx rule in ValidationRules)
|
||||
{
|
||||
if (rule.Controls.Contains(control))
|
||||
{
|
||||
ruleToEvaluete = rule;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ruleToEvaluete as FilterDescriptor;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
using System.ComponentModel;
|
||||
using System.Drawing.Design;
|
||||
using Telerik.WinControls;
|
||||
using Telerik.WinControls.Data;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Controls.RadValidationProvider;
|
||||
|
||||
/// <summary>
|
||||
/// RadValidationRule provides a validation logic which compares RadControl's Property with Rule's Value.
|
||||
/// </summary>
|
||||
public class RadValidationRuleEx : FilterDescriptor, IRadValidationRuleEx
|
||||
{
|
||||
#region Fields
|
||||
private List<Control> controls = [];
|
||||
private string toolTipText = string.Empty;
|
||||
private bool caseSensitive = false;
|
||||
private bool autoToolTip = false;
|
||||
private string toolTipTitle = "Validation Failed";
|
||||
#endregion
|
||||
|
||||
#region Cstor
|
||||
public RadValidationRuleEx() : base()
|
||||
{
|
||||
PropertyName = "Text";
|
||||
}
|
||||
|
||||
public RadValidationRuleEx(string propertyName, FilterOperator filterOperator) : base(propertyName, filterOperator, null)
|
||||
{
|
||||
}
|
||||
|
||||
public RadValidationRuleEx(string propertyName, FilterOperator filterOperator, object value) : base(propertyName, filterOperator, value)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// <para>Associates this rule with the specified RadControl descendant.</para>
|
||||
/// </summary>
|
||||
/// <param name="control">A RadControl descendant that represents the editor.</param>
|
||||
|
||||
public virtual void AddControl(RadControl control)
|
||||
{
|
||||
if (control != null && !controls.Contains(control))
|
||||
controls.Add(control);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Removes the specified RadControl descendant from this rule.</para>
|
||||
/// </summary>
|
||||
/// <param name="control">A RadControl descendant that represents the editor.</param>
|
||||
public virtual void RemoveControl(RadControl control)
|
||||
{
|
||||
if (control == null)
|
||||
return;
|
||||
|
||||
while (controls.Contains(control))
|
||||
{
|
||||
controls.Remove(control);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Inherit property. Not used in RadValidation Rule
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Browsable(false)]
|
||||
public override bool IsFilterEditor
|
||||
{
|
||||
get { return base.IsFilterEditor; }
|
||||
set { base.IsFilterEditor = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Associated RadControl descendants to this Rule
|
||||
/// </summary>
|
||||
[Editor(DesignerConsts.RadValidationRuleAssociatedControlsEditorString, typeof(UITypeEditor))]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||||
public List<Control> Controls
|
||||
{
|
||||
get
|
||||
{
|
||||
return controls;
|
||||
}
|
||||
set
|
||||
{
|
||||
controls = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Value of this rule. Controls in the rule will be evaluated against this value.
|
||||
/// </summary>
|
||||
[Editor(DesignerConsts.RadValidationRuleValueEditorString, typeof(UITypeEditor))]
|
||||
public override object Value
|
||||
{
|
||||
get { return base.Value; }
|
||||
set { base.Value = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the ToolTip Text. This text will be shown as ToolTip text when rule validation fails.
|
||||
/// </summary>
|
||||
[DefaultValue("")]
|
||||
public string ToolTipText
|
||||
{
|
||||
get { return toolTipText; }
|
||||
set { toolTipText = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable or Disable the ToolTip when validation fails.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
public bool AutoToolTip
|
||||
{
|
||||
get { return autoToolTip; }
|
||||
set { autoToolTip = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the ToolTip Title Text. This text will be shown as ToolTip Title text when rule validation fails.
|
||||
/// </summary>
|
||||
[DefaultValue("Validation Failed")]
|
||||
public string ToolTipTitle
|
||||
{
|
||||
get { return toolTipTitle; }
|
||||
set { toolTipTitle = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enable or Disable the case sensitive Rule's Like operator.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
public bool CaseSensitive
|
||||
{
|
||||
get { return caseSensitive; }
|
||||
set { caseSensitive = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Name of the Property from Control. This Property will be evaluated against the Rule's Value property.
|
||||
/// </summary>
|
||||
[DefaultValue("Text")]
|
||||
public override string PropertyName
|
||||
{
|
||||
get { return base.PropertyName; }
|
||||
set { base.PropertyName = value; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using System.ComponentModel;
|
||||
using Telerik.WinControls.Data;
|
||||
//using System.Linq;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Controls.RadValidationProvider;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// RadValidationRuleWithTargetControl provides a validation logic which compares RadControl's Property with TargetControl's property.
|
||||
/// </summary>
|
||||
public class RadValidationRuleWithTargetControlEx : RadValidationRuleEx
|
||||
{
|
||||
private string sourceControlPropertyName = "Text";
|
||||
|
||||
public RadValidationRuleWithTargetControlEx()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Target Control. This control's property value will be used in the Rule evaluation.
|
||||
/// </summary>
|
||||
[DefaultValue(null)]
|
||||
public Control TargetControl { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of the property that will be used in the Rule evaluation.
|
||||
/// </summary>
|
||||
[DefaultValue("Text")]
|
||||
public string TargetControlPropertyName
|
||||
{
|
||||
get { return sourceControlPropertyName; }
|
||||
set { sourceControlPropertyName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Rule expression.
|
||||
/// </summary>
|
||||
/// <value>The Rule expression.</value>
|
||||
public override string Expression
|
||||
{
|
||||
get
|
||||
{
|
||||
if (TargetControl != null)
|
||||
Value = CalculateValue();
|
||||
|
||||
return base.Expression;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Value of this rule. Controls in the rule will be evaluated against this value.
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Browsable(false)]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public override object Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (TargetControl != null && !string.IsNullOrEmpty(TargetControlPropertyName))
|
||||
{
|
||||
try
|
||||
{
|
||||
base.Value = RadValidationProviderEx.GetSubPropertyValue(TargetControl, TargetControlPropertyName);//TargetControl.GetType().GetProperty(TargetControlPropertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(TargetControl, null);
|
||||
}
|
||||
catch { }
|
||||
|
||||
}
|
||||
return base.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
|
||||
base.Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual object CalculateValue()
|
||||
{
|
||||
if (TargetControl.Site != null)
|
||||
return string.Format("{0}.{1}", TargetControl.Name, TargetControlPropertyName);
|
||||
|
||||
if (!string.IsNullOrEmpty(TargetControlPropertyName))
|
||||
{
|
||||
try
|
||||
{
|
||||
return RadValidationProviderEx.GetSubPropertyValue(TargetControl, TargetControlPropertyName);//this.TargetControl.GetType().GetProperty(this.TargetControlPropertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(this.TargetControl, null);
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
14
Pilz.UI.WinForms.Telerik/Dialogs/DialogClosedEventArgs.cs
Normal file
14
Pilz.UI.WinForms.Telerik/Dialogs/DialogClosedEventArgs.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Pilz.UI.Telerik.Dialogs;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Dialogs;
|
||||
|
||||
public class DialogClosedEventArgs : EventArgs
|
||||
{
|
||||
public RadDialogBase Parent { get; private set; }
|
||||
public RadFlyoutBase? Content => Parent?.DialogPanel;
|
||||
|
||||
public DialogClosedEventArgs(RadDialogBase dialog)
|
||||
{
|
||||
Parent = dialog;
|
||||
}
|
||||
}
|
||||
14
Pilz.UI.WinForms.Telerik/Dialogs/DialogLoadingEventArgs.cs
Normal file
14
Pilz.UI.WinForms.Telerik/Dialogs/DialogLoadingEventArgs.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Pilz.UI.Telerik.Dialogs;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Dialogs;
|
||||
|
||||
public class DialogLoadingEventArgs : EventArgs
|
||||
{
|
||||
public RadDialogBase Parent { get; private set; }
|
||||
public RadFlyoutBase? Content => Parent?.DialogPanel;
|
||||
|
||||
public DialogLoadingEventArgs(RadDialogBase dialog)
|
||||
{
|
||||
Parent = dialog;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Pilz.UI.Telerik.Dialogs;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Dialogs;
|
||||
|
||||
public class FlyoutClosedEventArgs(RadFlyoutBase content) : global::Telerik.WinControls.UI.SplashScreen.FlyoutClosedEventArgs(content)
|
||||
{
|
||||
public new RadFlyoutBase? Content => base.Content as RadFlyoutBase;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Pilz.UI.Telerik.Dialogs;
|
||||
using Telerik.WinControls.UI.SplashScreen;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Dialogs;
|
||||
|
||||
public class FlyoutCreatedEventArgs(RadFlyoutBase content) : ContentCreatedEventArgs(content)
|
||||
{
|
||||
public new RadFlyoutBase? Content => base.Content as RadFlyoutBase;
|
||||
}
|
||||
86
Pilz.UI.WinForms.Telerik/Dialogs/RadDialogBase.Statics.cs
Normal file
86
Pilz.UI.WinForms.Telerik/Dialogs/RadDialogBase.Statics.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using Pilz.UI.WinForms.Extensions;
|
||||
using Pilz.UI.WinForms.Telerik.Dialogs;
|
||||
using Pilz.UI.WinForms.Telerik.Extensions;
|
||||
using Telerik.WinControls;
|
||||
|
||||
namespace Pilz.UI.Telerik.Dialogs;
|
||||
|
||||
partial class RadDialogBase
|
||||
{
|
||||
public delegate void DialogLoadingEventHandler(DialogLoadingEventArgs e);
|
||||
public delegate void DialogClosedEventHandler(DialogClosedEventArgs e);
|
||||
|
||||
public static event DialogLoadingEventHandler? DialogLoading;
|
||||
public static event DialogClosedEventHandler? DialogClosed;
|
||||
|
||||
public static T Show<T>(string? title, object? icon, object? tag = null) where T : RadFlyoutBase
|
||||
{
|
||||
return Show<T>(null, title, icon, tag);
|
||||
}
|
||||
|
||||
public static T ShowDialog<T>(string? title, object? icon, object? tag = null) where T : RadFlyoutBase
|
||||
{
|
||||
return ShowDialog<T>(null, title, icon, tag);
|
||||
}
|
||||
|
||||
public static T Show<T>(IWin32Window? parent, string? title, object? icon, object? tag = null) where T : RadFlyoutBase
|
||||
{
|
||||
return Show(CreatePanelInstance<T>(tag), parent, title, icon);
|
||||
}
|
||||
|
||||
public static T ShowDialog<T>(IWin32Window? parent, string? title, object? icon, object? tag = null) where T : RadFlyoutBase
|
||||
{
|
||||
return ShowDialog(CreatePanelInstance<T>(tag), parent, title, icon);
|
||||
}
|
||||
|
||||
public static T Show<T>(T dialogPanel, string? title, object? icon) where T : RadFlyoutBase
|
||||
{
|
||||
return Show(dialogPanel, null, title, icon);
|
||||
}
|
||||
|
||||
public static T ShowDialog<T>(T dialogPanel, string? title, object? icon) where T : RadFlyoutBase
|
||||
{
|
||||
return ShowDialog(dialogPanel, null, title, icon);
|
||||
}
|
||||
|
||||
public static T Show<T>(T dialogPanel, IWin32Window? parent, string? title, object? icon) where T : RadFlyoutBase
|
||||
{
|
||||
CreateForm(dialogPanel, parent, title, icon).Show();
|
||||
return dialogPanel;
|
||||
}
|
||||
|
||||
public static T ShowDialog<T>(T dialogPanel, IWin32Window? parent, string? title, object? icon) where T : RadFlyoutBase
|
||||
{
|
||||
CreateForm(dialogPanel, parent, title, icon).ShowDialog();
|
||||
return dialogPanel;
|
||||
}
|
||||
|
||||
private static T CreatePanelInstance<T>(object? tag) where T : RadFlyoutBase
|
||||
{
|
||||
T dialogPanel = Activator.CreateInstance<T>();
|
||||
dialogPanel.Tag = tag;
|
||||
return dialogPanel;
|
||||
}
|
||||
|
||||
private static RadDialogBase CreateForm<T>(T dialogPanel, IWin32Window? parent, string? title, object? icon) where T : RadFlyoutBase
|
||||
{
|
||||
dialogPanel.Dock = DockStyle.Fill;
|
||||
|
||||
if (icon is RadSvgImage svg)
|
||||
icon = svg.ToImage();
|
||||
if (icon is Image img)
|
||||
icon = img.ToIcon();
|
||||
|
||||
var dialog = new RadDialogBase(dialogPanel)
|
||||
{
|
||||
Text = title,
|
||||
Icon = icon as Icon,
|
||||
StartPosition = parent == null ? FormStartPosition.CenterScreen : FormStartPosition.CenterParent,
|
||||
ClientSize = dialogPanel.Size
|
||||
};
|
||||
|
||||
dialog.Controls.Add(dialogPanel);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
35
Pilz.UI.WinForms.Telerik/Dialogs/RadDialogBase.cs
Normal file
35
Pilz.UI.WinForms.Telerik/Dialogs/RadDialogBase.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Pilz.UI.WinForms;
|
||||
using Telerik.WinControls.UI;
|
||||
|
||||
namespace Pilz.UI.Telerik.Dialogs;
|
||||
|
||||
public partial class RadDialogBase : RadForm
|
||||
{
|
||||
public RadFlyoutBase? DialogPanel { get; private set; }
|
||||
|
||||
private RadDialogBase()
|
||||
{
|
||||
Load += DialogBaseForm_Load;
|
||||
FormClosed += DialogBaseForm_FormClosed;
|
||||
}
|
||||
|
||||
public RadDialogBase(RadFlyoutBase dialogPanel) : this()
|
||||
{
|
||||
DialogPanel = dialogPanel;
|
||||
}
|
||||
|
||||
private void DialogBaseForm_Load(object? sender, EventArgs e)
|
||||
{
|
||||
if (DialogPanel is ILoadContent iLoadContent)
|
||||
iLoadContent.LoadContent();
|
||||
else if (DialogPanel is ILoadContentAsync iLoadContentAsync)
|
||||
Task.Run(iLoadContentAsync.LoadContentAsync).Wait();
|
||||
|
||||
DialogLoading?.Invoke(new DialogLoadingEventArgs(this));
|
||||
}
|
||||
|
||||
private void DialogBaseForm_FormClosed(object? sender, FormClosedEventArgs e)
|
||||
{
|
||||
DialogClosed?.Invoke(new DialogClosedEventArgs(this));
|
||||
}
|
||||
}
|
||||
115
Pilz.UI.WinForms.Telerik/Dialogs/RadFlyoutBase.Statics.cs
Normal file
115
Pilz.UI.WinForms.Telerik/Dialogs/RadFlyoutBase.Statics.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using Pilz.UI.WinForms;
|
||||
using Pilz.UI.WinForms.Telerik.Dialogs;
|
||||
using Telerik.WinControls;
|
||||
using Telerik.WinControls.UI;
|
||||
using Telerik.WinControls.UI.SplashScreen;
|
||||
|
||||
namespace Pilz.UI.Telerik.Dialogs;
|
||||
|
||||
partial class RadFlyoutBase
|
||||
{
|
||||
public delegate void FlyoutCreatedEventHandler(FlyoutCreatedEventArgs e);
|
||||
public delegate void FlyoutClosedEventHandler(FlyoutClosedEventArgs e);
|
||||
|
||||
public static event FlyoutCreatedEventHandler FlyoutCreated
|
||||
{
|
||||
add => flyoutCreatedHandlers.Add(value);
|
||||
remove => flyoutCreatedHandlers.Remove(value);
|
||||
}
|
||||
|
||||
public static event FlyoutClosedEventHandler FlyoutClosed
|
||||
{
|
||||
add => flyoutCloseHandlers.Add(value);
|
||||
remove => flyoutCloseHandlers.Remove(value);
|
||||
}
|
||||
|
||||
private static readonly List<FlyoutCreatedEventHandler> flyoutCreatedHandlers = [];
|
||||
private static readonly List<FlyoutClosedEventHandler> flyoutCloseHandlers = [];
|
||||
|
||||
private static object? tagToAssign = null;
|
||||
private static string? titleToAssing = null;
|
||||
private static RadSvgImage? iconToAssign = null;
|
||||
|
||||
public static Control? ParentContext { get; private set; } = null;
|
||||
|
||||
static RadFlyoutBase()
|
||||
{
|
||||
RadFlyoutManager.ContentCreated += RadFlyoutManager_ContentCreated;
|
||||
RadFlyoutManager.FlyoutClosed += RadFlyoutManager_FlyoutClosed;
|
||||
}
|
||||
|
||||
private static void RadFlyoutManager_ContentCreated(ContentCreatedEventArgs e)
|
||||
{
|
||||
if (e.Content is RadFlyoutBase dialogBase)
|
||||
{
|
||||
if (tagToAssign != null)
|
||||
dialogBase.Tag = tagToAssign;
|
||||
|
||||
if (titleToAssing != null)
|
||||
dialogBase.Title = titleToAssing;
|
||||
|
||||
if (iconToAssign != null)
|
||||
dialogBase.TitleIcon = iconToAssign;
|
||||
|
||||
var eventArgs = new FlyoutCreatedEventArgs(dialogBase);
|
||||
|
||||
if (dialogBase is ILoadContent iLoadContent)
|
||||
iLoadContent.LoadContent();
|
||||
else if (dialogBase is ILoadContentAsync iLoadContentAsync)
|
||||
Task.Run(iLoadContentAsync.LoadContentAsync).Wait();
|
||||
|
||||
foreach (var args in flyoutCreatedHandlers.ToArray())
|
||||
{
|
||||
if (ParentContext != null)
|
||||
ParentContext?.Invoke(args, eventArgs);
|
||||
else
|
||||
args.Invoke(eventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void RadFlyoutManager_FlyoutClosed(global::Telerik.WinControls.UI.SplashScreen.FlyoutClosedEventArgs e)
|
||||
{
|
||||
if (e.Content is RadFlyoutBase dialogBase)
|
||||
{
|
||||
var eventArgs = new FlyoutClosedEventArgs((RadFlyoutBase)e.Content);
|
||||
|
||||
foreach (var args in flyoutCloseHandlers.ToArray())
|
||||
{
|
||||
if (ParentContext != null)
|
||||
ParentContext?.Invoke(args, eventArgs);
|
||||
else
|
||||
args.Invoke(eventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
ParentContext = null;
|
||||
}
|
||||
|
||||
public static void Show<T>(Control controlToAssociate, object? tag = null)
|
||||
{
|
||||
Show<T>(controlToAssociate, null, null, tag: tag);
|
||||
}
|
||||
|
||||
public static void Show<T>(Control controlToAssociate, string? title, RadSvgImage? icon, object? tag = null)
|
||||
{
|
||||
Show(controlToAssociate, typeof(T), title, icon, tag: tag);
|
||||
}
|
||||
|
||||
public static void Show(Control controlToAssociate, Type flyoutContentType, string? title, RadSvgImage? icon, object? tag = null)
|
||||
{
|
||||
tagToAssign = tag;
|
||||
titleToAssing = title;
|
||||
iconToAssign = icon;
|
||||
ParentContext = controlToAssociate;
|
||||
CloseFlyout(); // Ensure it's closed!
|
||||
RadFlyoutManager.Show(controlToAssociate, flyoutContentType);
|
||||
}
|
||||
|
||||
protected static void CloseFlyout()
|
||||
{
|
||||
if (typeof(RadFlyoutManager).GetField("flyoutInstance", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static).GetValue(null) is FlyoutScreen instance
|
||||
&& instance.IsActive)
|
||||
RadFlyoutManager.Close();
|
||||
}
|
||||
}
|
||||
291
Pilz.UI.WinForms.Telerik/Dialogs/RadFlyoutBase.cs
Normal file
291
Pilz.UI.WinForms.Telerik/Dialogs/RadFlyoutBase.cs
Normal file
@@ -0,0 +1,291 @@
|
||||
using Pilz.UI.WinForms.Telerik.Controls.RadValidationProvider;
|
||||
using System.ComponentModel;
|
||||
using Telerik.WinControls;
|
||||
using Telerik.WinControls.Data;
|
||||
using Telerik.WinControls.UI;
|
||||
|
||||
namespace Pilz.UI.Telerik.Dialogs;
|
||||
|
||||
public partial class RadFlyoutBase : UserControl
|
||||
{
|
||||
private bool addedControlsToUi;
|
||||
|
||||
protected RadButton radButton_Cancel;
|
||||
protected RadButton radButton_Confirm;
|
||||
protected TableLayoutPanel tableLayoutPanel_ActionPanel;
|
||||
protected TableLayoutPanel tableLayoutPanel_TitlePanel;
|
||||
protected RadLabel radLabel_Title;
|
||||
|
||||
public static RadSvgImage? CancelSvg { get; set; } = null;
|
||||
public static RadSvgImage? ConfirmSvg { get; set; } = null;
|
||||
|
||||
[Browsable(false)]
|
||||
public RadValidationProviderEx ValidationProvider { get; } = new()
|
||||
{
|
||||
AllowCancelControlEvents = false,
|
||||
};
|
||||
|
||||
[ReadOnly(true)]
|
||||
public DialogResult Result { get; protected set; }
|
||||
|
||||
[DefaultValue(true)]
|
||||
public bool RegisterDialogAccept { get; set; } = true;
|
||||
|
||||
[DefaultValue(true)]
|
||||
public bool RegisterDialogCancel { get; set; } = true;
|
||||
|
||||
public new Size PreferredSize { get; set; } = Size.Empty;
|
||||
|
||||
[DefaultValue(true)]
|
||||
public virtual bool ActionPanelVisible
|
||||
{
|
||||
get => tableLayoutPanel_ActionPanel.Visible;
|
||||
set => tableLayoutPanel_ActionPanel.Visible = value;
|
||||
}
|
||||
|
||||
[DefaultValue(true)]
|
||||
public virtual bool CancelButtonVisible
|
||||
{
|
||||
get => radButton_Cancel.Visible;
|
||||
set => radButton_Cancel.Visible = value;
|
||||
}
|
||||
|
||||
[DefaultValue(true)]
|
||||
public virtual bool CancelButtonEnable
|
||||
{
|
||||
get => radButton_Cancel.Enabled;
|
||||
set => radButton_Cancel.Enabled = value;
|
||||
}
|
||||
|
||||
[DefaultValue(true)]
|
||||
public virtual bool ConfirmButtonEnable
|
||||
{
|
||||
get => radButton_Confirm.Enabled;
|
||||
set => radButton_Confirm.Enabled = value;
|
||||
}
|
||||
|
||||
[Localizable(true)]
|
||||
[DefaultValue("Okay")]
|
||||
public virtual string ConfirmButtonText
|
||||
{
|
||||
get => radButton_Confirm.Text;
|
||||
set => radButton_Confirm.Text = value;
|
||||
}
|
||||
|
||||
[Localizable(true)]
|
||||
[DefaultValue("Cancel")]
|
||||
public virtual string CancelButtonText
|
||||
{
|
||||
get => radButton_Cancel.Text;
|
||||
set => radButton_Cancel.Text = value;
|
||||
}
|
||||
|
||||
[Localizable(true)]
|
||||
[DefaultValue("")]
|
||||
public virtual string Title
|
||||
{
|
||||
get => radLabel_Title.Text;
|
||||
set
|
||||
{
|
||||
radLabel_Title.Text = value;
|
||||
SetShowTitlePanel();
|
||||
}
|
||||
}
|
||||
|
||||
[DefaultValue(null)]
|
||||
public virtual RadSvgImage TitleIcon
|
||||
{
|
||||
get => radLabel_Title.SvgImage;
|
||||
set
|
||||
{
|
||||
radLabel_Title.SvgImage = value;
|
||||
SetShowTitlePanel();
|
||||
}
|
||||
}
|
||||
|
||||
[DefaultValue(typeof(ValidationMode), "OnValidating")]
|
||||
public ValidationMode ValidationMode
|
||||
{
|
||||
get => ValidationProvider.ValidationMode;
|
||||
set => ValidationProvider.ValidationMode = value;
|
||||
}
|
||||
|
||||
protected RadFlyoutBase()
|
||||
{
|
||||
InitializeComponent();
|
||||
ParentChanged += FlyoutDialogBase_ParentChanged;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
// radButton_Cancel
|
||||
radButton_Cancel = new()
|
||||
{
|
||||
Name = "radButton_Cancel",
|
||||
Anchor = AnchorStyles.Bottom | AnchorStyles.Right,
|
||||
ImageAlignment = ContentAlignment.MiddleRight,
|
||||
Size = new Size(110, 24),
|
||||
TabIndex = 1,
|
||||
Text = "Cancel",
|
||||
TextAlignment = ContentAlignment.MiddleLeft,
|
||||
TextImageRelation = TextImageRelation.ImageBeforeText,
|
||||
SvgImage = CancelSvg
|
||||
};
|
||||
radButton_Cancel.TabIndex = int.MaxValue;
|
||||
radButton_Cancel.Click += RadButton_Cancel_Click;
|
||||
|
||||
// radButton_Confirm
|
||||
radButton_Confirm = new()
|
||||
{
|
||||
Name = "radButton_Confirm",
|
||||
Anchor = AnchorStyles.Bottom | AnchorStyles.Right,
|
||||
ImageAlignment = ContentAlignment.MiddleRight,
|
||||
Size = new Size(110, 24),
|
||||
TabIndex = 0,
|
||||
Text = "Okay",
|
||||
TextAlignment = ContentAlignment.MiddleLeft,
|
||||
TextImageRelation = TextImageRelation.ImageBeforeText,
|
||||
SvgImage = ConfirmSvg
|
||||
};
|
||||
radButton_Confirm.TabIndex = int.MaxValue - 1;
|
||||
radButton_Confirm.Click += RadButton_Confirm_Click;
|
||||
|
||||
// radLabel_Title
|
||||
radLabel_Title = new()
|
||||
{
|
||||
Name = "radLabel_Title",
|
||||
AutoSize = false,
|
||||
Dock = DockStyle.Fill,
|
||||
TabStop = false,
|
||||
TextImageRelation = TextImageRelation.ImageBeforeText
|
||||
};
|
||||
|
||||
// tableLayoutPanel_ActionPanel
|
||||
tableLayoutPanel_ActionPanel = new()
|
||||
{
|
||||
Name = "tableLayoutPanel_ActionPanel",
|
||||
Dock = DockStyle.Bottom,
|
||||
Size = new Size(ClientSize.Width, 30),
|
||||
TabStop = false,
|
||||
ColumnCount = 3,
|
||||
RowCount = 1,
|
||||
};
|
||||
tableLayoutPanel_ActionPanel.SuspendLayout();
|
||||
tableLayoutPanel_ActionPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
||||
tableLayoutPanel_ActionPanel.ColumnStyles.Add(new ColumnStyle());
|
||||
tableLayoutPanel_ActionPanel.ColumnStyles.Add(new ColumnStyle());
|
||||
tableLayoutPanel_ActionPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
|
||||
tableLayoutPanel_ActionPanel.Controls.Add(radButton_Confirm, 1, 0);
|
||||
tableLayoutPanel_ActionPanel.Controls.Add(radButton_Cancel, 2, 0);
|
||||
|
||||
// tableLayoutPanel_TitlePanel
|
||||
tableLayoutPanel_TitlePanel = new()
|
||||
{
|
||||
Name = "tableLayoutPanel_TitlePanel",
|
||||
Dock = DockStyle.Top,
|
||||
TabStop = false,
|
||||
Visible = false,
|
||||
ColumnCount = 1,
|
||||
RowCount = 1
|
||||
};
|
||||
tableLayoutPanel_TitlePanel.SuspendLayout();
|
||||
tableLayoutPanel_TitlePanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
|
||||
tableLayoutPanel_TitlePanel.Controls.Add(radLabel_Title, 0, 0);
|
||||
tableLayoutPanel_TitlePanel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
|
||||
tableLayoutPanel_TitlePanel.Size = new Size(300, 30);
|
||||
|
||||
// RadFlyoutBase
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
Size = new Size(300, 150);
|
||||
|
||||
tableLayoutPanel_TitlePanel.ResumeLayout(false);
|
||||
tableLayoutPanel_ActionPanel.ResumeLayout(false);
|
||||
}
|
||||
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
if (!addedControlsToUi && !DesignMode)
|
||||
{
|
||||
SuspendLayout();
|
||||
Controls.Add(tableLayoutPanel_ActionPanel);
|
||||
tableLayoutPanel_ActionPanel.SendToBack();
|
||||
Controls.Add(tableLayoutPanel_TitlePanel);
|
||||
tableLayoutPanel_TitlePanel.SendToBack();
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
SetShowTitlePanel();
|
||||
addedControlsToUi = true;
|
||||
}
|
||||
base.OnLoad(e);
|
||||
}
|
||||
|
||||
protected virtual void FlyoutDialogBase_ParentChanged(object? sender, EventArgs e)
|
||||
{
|
||||
var frm = FindForm();
|
||||
|
||||
if (frm != null)
|
||||
{
|
||||
if (RegisterDialogAccept)
|
||||
frm.AcceptButton = radButton_Confirm;
|
||||
|
||||
if (RegisterDialogCancel)
|
||||
{
|
||||
frm.CancelButton = radButton_Cancel;
|
||||
radButton_Cancel.DialogResult = DialogResult.None;
|
||||
}
|
||||
|
||||
if (AutoSize)
|
||||
{
|
||||
frm.AutoSize = true;
|
||||
frm.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
||||
}
|
||||
else
|
||||
{
|
||||
frm.ClientSize = Size;
|
||||
}
|
||||
|
||||
frm.Shown += Form_Shown;
|
||||
}
|
||||
}
|
||||
|
||||
private void Form_Shown(object? sender, EventArgs e)
|
||||
{
|
||||
if (FindForm() is not Form frm)
|
||||
return;
|
||||
|
||||
if (!AutoSize && !PreferredSize.IsEmpty)
|
||||
frm.ClientSize = PreferredSize;
|
||||
}
|
||||
|
||||
protected void Close(DialogResult result)
|
||||
{
|
||||
Result = result;
|
||||
|
||||
if (FindForm() is RadDialogBase dialogForm)
|
||||
dialogForm.Close();
|
||||
else
|
||||
CloseFlyout();
|
||||
}
|
||||
|
||||
protected virtual bool ValidateOK()
|
||||
{
|
||||
return ValidationProvider.ValidateAll();
|
||||
}
|
||||
|
||||
protected virtual void SetShowTitlePanel()
|
||||
{
|
||||
tableLayoutPanel_TitlePanel.Visible = !string.IsNullOrWhiteSpace(radLabel_Title.Text) || radLabel_Title.SvgImage != null;
|
||||
}
|
||||
|
||||
protected virtual void RadButton_Confirm_Click(object? sender, EventArgs e)
|
||||
{
|
||||
if (ValidateOK())
|
||||
Close(DialogResult.OK);
|
||||
}
|
||||
|
||||
protected virtual void RadButton_Cancel_Click(object? sender, EventArgs e)
|
||||
{
|
||||
Close(DialogResult.Cancel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Pilz.UI.Telerik.Dialogs;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Extensions;
|
||||
|
||||
public static class RadFlyoutBaseExtensions
|
||||
{
|
||||
public static bool IsValid(this RadFlyoutBase? @this)
|
||||
{
|
||||
return @this != null && @this.Result == DialogResult.OK;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Telerik.WinControls.UI;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Extensions;
|
||||
|
||||
public static class RadListDataItemCollectionExtensions
|
||||
{
|
||||
public static IEnumerable<RadListDataItem> AddEnumValues<T>(this RadListDataItemCollection @this) where T : struct, Enum
|
||||
{
|
||||
return @this.AddEnumValues<T>(false);
|
||||
}
|
||||
|
||||
public static IEnumerable<RadListDataItem> AddEnumValues<T>(this RadListDataItemCollection @this, bool clearCollection) where T : struct, Enum
|
||||
{
|
||||
return @this.AddEnumValues<T>(clearCollection, null, null);
|
||||
}
|
||||
|
||||
public static IEnumerable<RadListDataItem> AddEnumValues<T>(this RadListDataItemCollection @this, bool clearCollection, Func<T, bool>? filter, Func<T, string?>? format) where T : struct, Enum
|
||||
{
|
||||
var values = Enum.GetValues(typeof(T));
|
||||
var items = new List<RadListDataItem>();
|
||||
|
||||
format ??= v => Enum.GetName(typeof(T), v);
|
||||
|
||||
if (clearCollection)
|
||||
@this.Clear();
|
||||
|
||||
foreach (T value in values)
|
||||
{
|
||||
if (filter is null || filter(value))
|
||||
items.Add(new(format(value), value));
|
||||
}
|
||||
|
||||
@this.AddRange(items);
|
||||
|
||||
return items;
|
||||
}
|
||||
}
|
||||
23
Pilz.UI.WinForms.Telerik/Extensions/RadSvgImageExtensions.cs
Normal file
23
Pilz.UI.WinForms.Telerik/Extensions/RadSvgImageExtensions.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Telerik.WinControls;
|
||||
using Telerik.WinControls.Svg;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Extensions;
|
||||
|
||||
public static class RadSvgImageExtensions
|
||||
{
|
||||
public static Image ToImage(this RadSvgImage svg)
|
||||
{
|
||||
return svg.Document.Draw(svg.Width, svg.Height);
|
||||
}
|
||||
|
||||
public static void ApplyColor(this RadSvgImage svg, Color color)
|
||||
{
|
||||
svg.Document.Fill = new SvgColourServer(color);
|
||||
svg.Document.ApplyRecursive(e =>
|
||||
{
|
||||
e.Fill = new SvgColourServer(color);
|
||||
e.Stroke = new SvgColourServer(color);
|
||||
});
|
||||
svg.ClearCache();
|
||||
}
|
||||
}
|
||||
12
Pilz.UI.WinForms.Telerik/Patches/Patches.cs
Normal file
12
Pilz.UI.WinForms.Telerik/Patches/Patches.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using HarmonyLib;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Patches;
|
||||
|
||||
public static class Patches
|
||||
{
|
||||
public static void Initialize(Harmony harmony)
|
||||
{
|
||||
harmony.PatchAll(Assembly.GetExecutingAssembly());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using HarmonyLib;
|
||||
using Telerik.WinControls.UI;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Patches.TelerikUiForWinForms;
|
||||
|
||||
[HarmonyPatch(typeof(RadPictureBoxElement))]
|
||||
[HarmonyPatch("PasteImage")]
|
||||
public class RadPictureBoxElement_PasteImageFixes
|
||||
{
|
||||
private static readonly Dictionary<RadPictureBoxElement, Image> images = [];
|
||||
|
||||
public static void Prefix(object __instance)
|
||||
{
|
||||
if (__instance is RadPictureBoxElement pb)
|
||||
{
|
||||
// Remember our image
|
||||
images.Remove(pb);
|
||||
images.Add(pb, pb.Image);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Postfix(object __instance)
|
||||
{
|
||||
if (__instance is RadPictureBoxElement pb && images.TryGetValue(pb, out var image))
|
||||
{
|
||||
// Remove first to avoid conflicts on error
|
||||
images.Remove(pb);
|
||||
|
||||
// Call "OnImageLoaded"
|
||||
if (pb.Image != image)
|
||||
typeof(RadPictureBoxElement).GetMethod("OnImageLoaded", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)?.Invoke(pb, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Pilz.UI.WinForms.Telerik/Pilz.UI.WinForms.Telerik.csproj
Normal file
29
Pilz.UI.WinForms.Telerik/Pilz.UI.WinForms.Telerik.csproj
Normal file
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0-windows</TargetFrameworks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>annotations</Nullable>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>2.12.0</Version>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Lib.Harmony" Version="2.3.6">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Telerik.UI.for.WinForms.AllControls" Version="2025.1.211">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Pilz.UI.WinForms\Pilz.UI.WinForms.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
15
Pilz.UI.WinForms.Telerik/Symbols/IRadSymbolFactory.cs
Normal file
15
Pilz.UI.WinForms.Telerik/Symbols/IRadSymbolFactory.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Pilz.UI.WinForms.Symbols;
|
||||
using Telerik.WinControls;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Symbols;
|
||||
|
||||
public interface IRadSymbolFactory<TSymbols> : ISymbolFactory<TSymbols>
|
||||
{
|
||||
Image GetImageColored(TSymbols svgImage, Size size, Color color);
|
||||
Image GetImageColored(TSymbols svgImage, SymbolSize size, Color color);
|
||||
Image GetImageFromSvg(RadSvgImage svg);
|
||||
RadSvgImage GetSvgImage(TSymbols svgImage, Size size);
|
||||
RadSvgImage GetSvgImage(TSymbols svgImage, SymbolSize size);
|
||||
RadSvgImage GetSvgImageColored(TSymbols svgImage, Size size, Color color);
|
||||
RadSvgImage GetSvgImageColored(TSymbols svgImage, SymbolSize size, Color color);
|
||||
}
|
||||
61
Pilz.UI.WinForms.Telerik/Symbols/RadSymbolFactory.cs
Normal file
61
Pilz.UI.WinForms.Telerik/Symbols/RadSymbolFactory.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using Pilz.UI.WinForms.Symbols;
|
||||
using Pilz.UI.WinForms.Telerik.Extensions;
|
||||
using Telerik.WinControls;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Symbols;
|
||||
|
||||
public abstract class RadSymbolFactory<TSymbols> : SymbolFactory<TSymbols>, IRadSymbolFactory<TSymbols>
|
||||
{
|
||||
public virtual RadSvgImage GetSvgImage(TSymbols svgImage, Size size)
|
||||
{
|
||||
using var stream = GetImageRessourceStream(svgImage);
|
||||
var img = RadSvgImage.FromStream(stream);
|
||||
|
||||
if (!size.IsEmpty)
|
||||
img.Size = size;
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
public virtual RadSvgImage GetSvgImageColored(TSymbols svgImage, SymbolSize size, Color color)
|
||||
{
|
||||
return GetSvgImageColored(svgImage, ResolveCommonSize(size), color);
|
||||
}
|
||||
|
||||
public virtual RadSvgImage GetSvgImageColored(TSymbols svgImage, Size size, Color color)
|
||||
{
|
||||
var img = GetSvgImage(svgImage, size);
|
||||
img.ApplyColor(color);
|
||||
return img;
|
||||
}
|
||||
|
||||
public override Image GetImage(TSymbols svgImage, SymbolSize size)
|
||||
{
|
||||
return GetImage(svgImage, ResolveCommonSize(size));
|
||||
}
|
||||
|
||||
public override Image GetImage(TSymbols svgImage, Size size)
|
||||
{
|
||||
return GetImageFromSvg(GetSvgImage(svgImage, size));
|
||||
}
|
||||
|
||||
public RadSvgImage GetSvgImage(TSymbols svgImage, SymbolSize size)
|
||||
{
|
||||
return GetSvgImage(svgImage, ResolveCommonSize(size));
|
||||
}
|
||||
|
||||
public virtual Image GetImageColored(TSymbols svgImage, SymbolSize size, Color color)
|
||||
{
|
||||
return GetImageColored(svgImage, ResolveCommonSize(size), color);
|
||||
}
|
||||
|
||||
public virtual Image GetImageColored(TSymbols svgImage, Size size, Color color)
|
||||
{
|
||||
return GetImageFromSvg(GetSvgImageColored(svgImage, size, color));
|
||||
}
|
||||
|
||||
public virtual Image GetImageFromSvg(RadSvgImage svg)
|
||||
{
|
||||
return svg.ToImage();
|
||||
}
|
||||
}
|
||||
9
Pilz.UI.WinForms.Telerik/Theming/ApplicationTheme.cs
Normal file
9
Pilz.UI.WinForms.Telerik/Theming/ApplicationTheme.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Pilz.UI.WinForms.Telerik.Theming;
|
||||
|
||||
public enum ApplicationTheme
|
||||
{
|
||||
Auto,
|
||||
Light,
|
||||
Dark,
|
||||
Gray,
|
||||
}
|
||||
8
Pilz.UI.WinForms.Telerik/Theming/HighContrastMode.cs
Normal file
8
Pilz.UI.WinForms.Telerik/Theming/HighContrastMode.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Pilz.UI.WinForms.Telerik.Theming;
|
||||
|
||||
public enum HighContrastMode
|
||||
{
|
||||
Auto,
|
||||
Enable,
|
||||
Disable,
|
||||
}
|
||||
17
Pilz.UI.WinForms.Telerik/Theming/ThemeDefinition.cs
Normal file
17
Pilz.UI.WinForms.Telerik/Theming/ThemeDefinition.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace Pilz.UI.WinForms.Telerik.Theming;
|
||||
|
||||
public class ThemeDefinition
|
||||
{
|
||||
public ApplicationTheme Theme { get; set; }
|
||||
public HighContrastMode HighContrast { get; set; }
|
||||
|
||||
public ThemeDefinition()
|
||||
{
|
||||
}
|
||||
|
||||
public ThemeDefinition(ApplicationTheme theme, HighContrastMode highContrast)
|
||||
{
|
||||
Theme = theme;
|
||||
HighContrast = highContrast;
|
||||
}
|
||||
}
|
||||
59
Pilz.UI.WinForms.Telerik/Theming/ThemeHelper.cs
Normal file
59
Pilz.UI.WinForms.Telerik/Theming/ThemeHelper.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using Telerik.WinControls;
|
||||
|
||||
namespace Pilz.UI.WinForms.Telerik.Theming;
|
||||
|
||||
public static class ThemeHelper
|
||||
{
|
||||
[Obsolete()]
|
||||
public static void ApplyApplicationTheme(ApplicationTheme theme, Func<RadThemeComponentBase> getLightTheme, Func<RadThemeComponentBase> getDarkTheme)
|
||||
{
|
||||
ApplyApplicationTheme(theme, getLightTheme, getDarkTheme, getDarkTheme);
|
||||
}
|
||||
|
||||
[Obsolete()]
|
||||
public static void ApplyApplicationTheme(ApplicationTheme theme, Func<RadThemeComponentBase> getLightTheme, Func<RadThemeComponentBase> getDarkTheme, Func<RadThemeComponentBase> getGrayTheme)
|
||||
{
|
||||
ApplyApplicationTheme(new(theme, HighContrastMode.Auto), def => def.Theme switch
|
||||
{
|
||||
ApplicationTheme.Light => getLightTheme(),
|
||||
ApplicationTheme.Dark => getDarkTheme(),
|
||||
ApplicationTheme.Gray => getGrayTheme(),
|
||||
_ => throw new NotImplementedException(),
|
||||
});
|
||||
}
|
||||
|
||||
public static void ApplyApplicationTheme(ThemeDefinition themeDefinition, Func<ThemeDefinition, RadThemeComponentBase> getTheme)
|
||||
{
|
||||
ThemeResolutionService.ApplicationThemeName = GetThemeName(themeDefinition, getTheme).ThemeName;
|
||||
}
|
||||
|
||||
public static RadThemeComponentBase GetThemeName(ThemeDefinition themeDefinition, Func<ThemeDefinition, RadThemeComponentBase> getTheme)
|
||||
{
|
||||
ApplicationTheme themeToUse;
|
||||
HighContrastMode highContrast;
|
||||
|
||||
if (themeDefinition.HighContrast == HighContrastMode.Enable || themeDefinition.HighContrast == HighContrastMode.Auto && SystemInformation.HighContrast)
|
||||
highContrast = HighContrastMode.Enable;
|
||||
else
|
||||
highContrast = HighContrastMode.Disable;
|
||||
|
||||
if (themeDefinition.Theme == ApplicationTheme.Light || themeDefinition.Theme == ApplicationTheme.Auto && WindowsSettings.AppsUseLightTheme)
|
||||
themeToUse = ApplicationTheme.Light;
|
||||
else if (themeDefinition.Theme == ApplicationTheme.Dark || themeDefinition.Theme == ApplicationTheme.Auto && !WindowsSettings.AppsUseLightTheme)
|
||||
themeToUse = ApplicationTheme.Dark;
|
||||
else
|
||||
themeToUse = ApplicationTheme.Gray;
|
||||
|
||||
return getTheme(new(themeToUse, highContrast));
|
||||
}
|
||||
|
||||
public static bool IsDarkTheme(ApplicationTheme theme)
|
||||
{
|
||||
return theme == ApplicationTheme.Dark || theme == ApplicationTheme.Gray || theme == ApplicationTheme.Auto && !WindowsSettings.AppsUseLightTheme;
|
||||
}
|
||||
|
||||
public static bool IsHighContrast(HighContrastMode theme)
|
||||
{
|
||||
return theme == HighContrastMode.Enable || theme == HighContrastMode.Auto && SystemInformation.HighContrast;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user