To reproduce: - Set the NullableValue property to null. - When you start the application there is no date in datetime picker but when the control loses the focus the date is automatically filled. Workaround: - Set the NullDate to equals the Value: radDateTimePicker1.NullDate = radDateTimePicker1.Value; - Then you change the NullDate in the ValueChanged event: void radDateTimePicker1_ValueChanged(object sender, EventArgs e) { radDateTimePicker1.NullDate = new DateTime(1980, 1, 1); }
To reproduce: -add RadGridView and use the following code: public static readonly DateTime MIN_DATE = new DateTime(1900, 1, 1); public static readonly DateTime MAX_DATE = new DateTime(2079, 1, 1); public Form1() { InitializeComponent(); var colDate = new Telerik.WinControls.UI.GridViewDateTimeColumn(); colDate.DataType = typeof(System.DateTime); colDate.HeaderText = "Date"; colDate.Name = "colDate"; colDate.FormatString = "{0:d}"; colDate.Width = 85; radGridView1.Columns.Add(colDate); radGridView1.CellEditorInitialized += radGridView1_CellEditorInitialized; } private void radGridView1_CellEditorInitialized(object sender, Telerik.WinControls.UI.GridViewCellEventArgs e) { var editor = this.radGridView1.ActiveEditor as RadDateTimeEditor; if (editor == null) { return; } editor.MinValue = MIN_DATE; editor.MaxValue = MAX_DATE; DateTime date = DateTime.Now; RadDateTimeEditorElement editorElement = (RadDateTimeEditorElement)editor.EditorElement; editorElement.Format = DateTimePickerFormat.Custom; editorElement.CustomFormat = "MM/dd/yyyy"; editorElement.Value = date; e.Row.Cells[e.ColumnIndex].Value = editorElement.Value; } As a result when the user tries to enter a valid year between MinValue and MaxValue it is not possible. Workaround: use CellValidating event: radGridView1.CellValidating += radGridView1_CellValidating; private void radGridView1_CellValidating(object sender, CellValidatingEventArgs e) { RadGridView grid = sender as RadGridView; if (grid.CurrentColumn is GridViewDateTimeColumn) { DateTime currentDate = (DateTime)e.Value; if (currentDate <= MAX_DATE && currentDate >= MIN_DATE) { e.Cancel = false; } else { e.Cancel = true; } } }
To reproduce: Add a RadTextBoxControl to a form, insert a text using the following line: this.radTextBoxControl1.AppendText(string.Format("{0} Foo {0} bar {0}", Environment.NewLine)); You will notice that the newlines are not taken into consideration Workaround: Use the following classes - public class MyTextBoxControl : RadTextBoxControl { protected override RadTextBoxControlElement CreateTextBoxElement() { return new MyTextBoxControlElement(); } } public class MyTextBoxControlElement : RadTextBoxControlElement { protected override TextBoxViewElement CreateViewElement() { return new MyTextBoxViewElement(); } protected override Type ThemeEffectiveType { get { return typeof(RadTextBoxControlElement); } } } public class MyTextBoxViewElement : TextBoxViewElement { protected override void ReplaceTextBlock(ITextBlock targetBlock, int startCharPosition, int endCharPosition, string text) { if (string.IsNullOrEmpty(text) && startCharPosition == 0 && endCharPosition == targetBlock.Length) { this.Children.Remove(targetBlock as RadElement); return; } string headText = targetBlock.Text.Substring(0, startCharPosition); string tailText = targetBlock.Text.Substring(endCharPosition); targetBlock.Text = headText; if (TextBoxViewElement.IsSpecialText(text) || this.ContainsNewLine(text)) { int index = string.IsNullOrEmpty(headText) ? targetBlock.Index : targetBlock.Index + 1; index = this.InsertTextBlocks(index, text, TextBlockElementType); if (string.IsNullOrEmpty(headText)) { targetBlock.Index = index + 1; } if (!string.IsNullOrEmpty(headText) && !string.IsNullOrEmpty(tailText)) { index = this.InsertTextBlocks(index + 1, tailText, TextBlockElementType); return; } } else { targetBlock.Text += text; } targetBlock.Text += tailText; } public bool ContainsNewLine(string text) { string[] words = text.Split(new char[] { ' ', ',', '.', '!', '?' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < words.Length; i++) { string word = words[i]; if (!string.IsNullOrEmpty(word) && word == Environment.NewLine) { return true; } } return false; } }
To reproduce: public Form1() { InitializeComponent(); this.radMaskedEditBox1.Mask = "00,000-000"; this.radMaskedEditBox1.MaskType = Telerik.WinControls.UI.MaskType.Standard; } private void radButton1_Click(object sender, EventArgs e) { radMaskedEditBox1.Value = null; } Workaround: private void radButton1_Click(object sender, EventArgs e) { radMaskedEditBox1.Value = null; radMaskedEditBox1.Text = ""; }
To reproduce: Add a RadSpellChecker and a RichTextBox, set the spell checker to check the RichTextBox on some button click. Set the main form's TopMost property to true. Start the form, you will notice that sometimes the dialog for spellchecking and the complete messagebox show behind the main form. Workaround: public class MyRadSpellChecker : RadSpellChecker { private FormSettings formSettingsForCurrentSpellCheckIteration = new FormSettings(); public MyRadSpellChecker() { } protected override void CheckAllAtOnce(IControlSpellChecker spellChecker) { Form spellCheckerParentForm = this.GetSpellCheckerParentForm(spellChecker); RadDocument editingElementContentToRadDocument = spellChecker.GetContentAsDocument(); editingElementContentToRadDocument.Measure(RadDocument.MAX_DOCUMENT_SIZE); IControlSpellChecker richTextBoxSpellChecker = this.GetControlSpellChecker(typeof(RadRichTextBox)); SpellCheckAllAtOnceForm checkAllAtOnceWindow = new SpellCheckAllAtOnceForm(editingElementContentToRadDocument, richTextBoxSpellChecker, spellChecker); if (!checkAllAtOnceWindow.HasErrors) { this.ShowSpellCheckingCompleteDialog(spellCheckerParentForm); return; } this.CopyFormSettings(this.FormSettings, checkAllAtOnceWindow); SpellingFormShowingEventArgs args = new SpellingFormShowingEventArgs(checkAllAtOnceWindow, spellChecker); this.OnSpellingFormShowing(args); if (args.Cancel) { return; } Form form = args.SpellingForm; form.ShowDialog(spellCheckerParentForm); } private void CopyFormSettings(FormSettings from, RadForm to) { to.Location = from.Location; to.StartPosition = from.StartPosition; ThemeResolutionService.ApplyThemeToControlTree(to, from.ThemeName); } private void ShowSpellCheckingCompleteDialog(Form parentForm = null) { if (this.EnableCompleteMessageBox) { string themeName = RadMessageBox.ThemeName; RadMessageBox.ThemeName = this.ThemeName; string title = RadSpellCheckerLocalizationProvider.CurrentProvider.GetLocalizedString(RadSpellCheckerStringId.Title); string complete = RadSpellCheckerLocalizationProvider.CurrentProvider.GetLocalizedString(RadSpellCheckerStringId.Complete); RadMessageBox.Show(parentForm, complete, title, MessageBoxButtons.OK); RadMessageBox.ThemeName = themeName; } } protected override void CheckWordByWord(IControlSpellChecker spellChecker) { this.CopyWindowSettings(this.FormSettings, this.formSettingsForCurrentSpellCheckIteration); DialogResult result = DialogResult.None; do { result = this.ShowWindowForNextError(spellChecker); } while (result != DialogResult.None && result == DialogResult.OK); } private void CopyWindowSettings(FormSettings from, FormSettings to) { to.Location = from.Location; to.StartPosition = from.StartPosition; to.ThemeName = from.ThemeName; } private DialogResult ShowWindowForNextError(IControlSpellChecker spellChecker) { Form spellCheckerParentForm = this.GetSpellCheckerParentForm(spellChecker); spellChecker.ResetFields(); IWordInfo incorrectWordInfo = spellChecker.MoveToNextError(); if (incorrectWordInfo == null) { this.ShowSpellCheckingCompleteDialog(spellCheckerParentForm); return DialogResult.None; } RadForm checkWordByWordWindow = new SpellCheckWordByWordForm(incorrectWordInfo.Word, spellChecker); this.CopyFormSettings(this.formSettingsForCurrentSpellCheckIteration, checkWordByWordWindow); SpellingFormShowingEventArgs args = new SpellingFormShowingEventArgs(checkWordByWordWindow, spellChecker); this.OnSpellingFormShowing(args); if (args.Cancel) { return DialogResult.None; } checkWordByWordWindow = args.SpellingForm; spellChecker.CurrentControl.Focus(); return checkWordByWordWindow.ShowDialog(spellCheckerParentForm); } private Form GetSpellCheckerParentForm(IControlSpellChecker spellChecker) { if (spellChecker != null && spellChecker.CurrentControl != null) { return spellChecker.CurrentControl.FindForm(); } return null; } }
To reproduce: Add a TableLayout and in the cells add a RadtextBox with its multiline property set to true. Resize the form until the textboxes and unclickable and no scrollbars are shown. This behavior does not always occur. Workaround: Use a custom RadTextBox class: public class MyTextBox : RadTextBox { protected override void InitializeTextElement() { this.GetType().BaseType.GetField("textBoxElement", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, new MyTextBoxElement()); this.TextBoxElement.StretchVertically = true; this.TextBoxElement.ShowBorder = true; } } public class MyTextBoxElement : RadTextBoxElement { protected override SizeF MeasureOverride(SizeF availableSize) { availableSize.Width -= BorderThickness.Size.Width; availableSize.Height -= BorderThickness.Size.Height; SizeF desiredSize = this.MeasureChildren(availableSize); return desiredSize; } protected override Type ThemeEffectiveType { get { return typeof(RadTextBoxElement); } } }
To reproduce: Add a radspellchecker and let it check a radrichtextbox. Check an incorrect word and click ignore all. You will see that the dialog shows up again. Workaround: public class MySpellCheckWordByWordForm : SpellCheckWordByWordForm {
Add a possibility to suggest misspelled words if they are all capital letters or contains numbers.
To reproduce: -add RadDateTimePicker and apply Windows7 theme -enable calendar footer -when opening the drop down calendar, the date part in the footer is not displayed correctly Workaround: RadDateTimePickerCalendar calendarBehavior = this.radDateTimePicker1.DateTimePickerElement.GetCurrentBehavior() as RadDateTimePickerCalendar; RadCalendar calendar = calendarBehavior.Calendar as RadCalendar; calendar.ShowFooter = true; calendarBehavior.PopupControl.PopupOpening += PopupControl_PopupOpening; private void PopupControl_PopupOpening(object sender, CancelEventArgs args) { RadDateTimePickerDropDown popup = sender as RadDateTimePickerDropDown; if (popup != null) { popup.Height = 250; popup.Width = 280; } }
To reproduce: use the following code: public Form1() { InitializeComponent(); RadMaskedEditBox maskControl = new RadMaskedEditBox(); maskControl.TextMaskFormat = System.Windows.Forms.MaskFormat.ExcludePromptAndLiterals; CultureInfo ci = CultureInfo.CreateSpecificCulture(Thread.CurrentThread.CurrentCulture.Name); ci.NumberFormat.NumberGroupSeparator = ""; maskControl.Culture = ci; maskControl.Text = "2"; object o = maskControl.Value; //Exception!! this.Controls.Add(maskControl); } Workaround: Do not set NumberGroupSeparator to String.Empty when TextMaskFormat=ExcludePromptAndLiterals
Add option to RadSpellChecker which will allow you to append the newly added words to the loaded dictionary and save them on the hard drive.
To reproduce: -add a RadTimePicker; -change its culture: this.radTimePicker1.Culture = new System.Globalization.CultureInfo("en-GB"); Workaround: public Form1() { InitializeComponent(); this.radTimePicker1.Culture = new System.Globalization.CultureInfo("en-GB"); this.radTimePicker1.TimePickerElement.PopupForm.Height =350; }
RadMaskedEditBox - the ability to access the ErrorProvider in order to change the image or other properties.
To reproduce: - Add RadDateTimePicker to a form and set its ReadOnly property to true. - Paste a valid value using the Ctrl+V key combination. Workaround: - Disable the corresponding key combination in the KeyDown event: void radDateTimePicker1_KeyDown(object sender, KeyEventArgs e) { if (e.Control && e.KeyCode == Keys.V) { e.SuppressKeyPress = true; } }
To reproduce: - Add RadMaskedEditBox to a form and set its ReadOnly property to true. - Paste a valid value using the Ctrl+V key combination. Workaround: - Disable the corresponding key combination in the KeyDown event: void radMaskedEditBox1_KeyDown(object sender, KeyEventArgs e) { if (e.Control && e.KeyCode == Keys.V) { e.SuppressKeyPress = true; } }
To reproduce: - Subscribe to MaskedEditBox Element PropertyChanged event. - You will notice that when you changing the value will not raise the event. Workaround: You can track the Text property for changes and parse the text to appropriate value.
Description: When binding to a null value, the RadSpinEditor throws an exception. This missing functionality is also noticed with the standard Windows Numeric Up Down control. How to reproduce: - add a RadSpinEditor and two RadButtons; - use the following code: public partial class Form1 : Form { private BindingSource _bindActiveObject = new BindingSource { DataSource = typeof(MyBindingObject) }; public Form1() { InitializeComponent(); this.radSpinEditor1.DataBindings.Add(new Binding("Value", _bindActiveObject, "MyValue")); } private void radButton1_Click(object sender, EventArgs e) { _bindActiveObject.DataSource = new MyBindingObject { MyValue = Convert.ToDouble(100) }; } private void radButton2_Click(object sender, EventArgs e) { _bindActiveObject.DataSource = new MyBindingObject { MyValue = null }; } } public class MyBindingObject { private decimal? _myValue; public decimal? MyValue { get { return _myValue; } set { _myValue = value; } } } Workaround: Use the following custom RadSpinEditor: private BindingSource _bindActiveObject = new BindingSource { DataSource = typeof(MyBindingObject) }; public Form1() { InitializeComponent(); this.radSpinEditor1.NullableValueChanged += Form1_NullableValueChanged; this.radSpinEditor1.DecimalPlaces = 2; this.radSpinEditor1.DataBindings.Add(new Binding("NullableValue", _bindActiveObject, "MyValue", true, DataSourceUpdateMode.OnPropertyChanged)); } private void Form1_NullableValueChanged(object sender, EventArgs e) { Console.WriteLine("NullableValue = " + this.radSpinEditor1.NullableValue + ""); } private void radButton1_Click(object sender, EventArgs e) { MyBindingObject obj = new MyBindingObject { MyValue = 65.45m }; _bindActiveObject.DataSource = obj; } private void radButton2_Click(object sender, EventArgs e) { _bindActiveObject.DataSource = new MyBindingObject { MyValue = null }; } public class MyBindingObject { private decimal? _myValue; public decimal? MyValue { get { return _myValue; } set { _myValue = value; } } } public class MySpinEditor : RadSpinEditor { public event EventHandler NullableValueChanged; public decimal? NullableValue { get { return (this.SpinElement as MySpinEditorElement).NullableValue; } set { (this.SpinElement as MySpinEditorElement).NullableValue = value; } } public MySpinEditor() { this.AutoSize = true; this.TabStop = false; base.SetStyle(ControlStyles.Selectable, true); } protected override void CreateChildItems(RadElement parent) { Type baseType = typeof(RadSpinEditor); MySpinEditorElement element = new MySpinEditorElement(); element.RightToLeft = this.RightToLeft == System.Windows.Forms.RightToLeft.Yes; this.RootElement.Children.Add(element); element.ValueChanging += spinElement_ValueChanging; element.ValueChanged += spinElement_ValueChanged; element.TextChanging += spinElement_TextChanging; element.NullableValueChanged += element_NullableValueChanged; element.KeyDown += OnSpinElementKeyDown; element.KeyPress += OnSpinElementKeyPress; element.KeyUp += OnSpinElementKeyUp; baseType.GetField("spinElement", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, element); } void element_NullableValueChanged(object sender, EventArgs e) { if (this.NullableValueChanged != null) { this.NullableValueChanged(this, EventArgs.Empty); } } private Dictionary<string, MethodInfo> cache = new Dictionary<string, MethodInfo>(); private void InvokeBaseMethod(string name, params object[] parameters) { if (!cache.ContainsKey(name)) { cache[name] = typeof(RadSpinEditor).GetMethod(name, BindingFlags.Instance | BindingFlags.NonPublic); } cache[name].Invoke(this, parameters); } private void OnSpinElementKeyUp(object sender, KeyEventArgs e) { this.InvokeBaseMethod("OnSpinElementKeyUp", sender, e); } private void OnSpinElementKeyPress(object sender, KeyPressEventArgs e) { this.InvokeBaseMethod("OnSpinElementKeyPress", sender, e); } private void OnSpinElementKeyDown(object sender, KeyEventArgs e) { this.InvokeBaseMethod("OnSpinElementKeyDown", sender, e); } private void spinElement_TextChanging(object sender, TextChangingEventArgs e) { this.InvokeBaseMethod("spinElement_TextChanging", sender, e); } private void spinElement_ValueChanged(object sender, EventArgs e) { this.InvokeBaseMethod("spinElement_ValueChanged", sender, e); this.NullableValue = this.Value; } private void spinElement_ValueChanging(object sender, ValueChangingEventArgs e) { this.InvokeBaseMethod("spinElement_ValueChanging", sender, e); } protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (keyData == Keys.Tab) { (this.SpinElement as MySpinEditorElement).CommitText(); } else if (keyData== Keys.Delete) { (this.SpinElement as MySpinEditorElement).NullableValue = null; } return base.ProcessCmdKey(ref msg, keyData); } protected override Size DefaultSize { get { return GetDpiScaledSize(new Size(100, 20)); } } } public class MySpinEditorElement : RadSpinElement { private bool validating; private decimal? nullableValue; private RadButtonElement nullButton; public decimal? NullableValue { get { return this.nullableValue; } set { this.nullableValue = value; if (value.HasValue) { this.internalValue = value.Value; } else { this.internalValue = 0m; } this.Validate(); this.OnNullableValueChanged(); } } protected override void OnKeyDown(KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { this.CommitText(); e.Handled = true; return; } base.OnKeyDown(e); } void nullButton_Click(object sender, EventArgs e) { this.NullableValue = null; } public virtual void CommitText() { this.NullableValue = this.GetValueFromText(); } protected override decimal GetValueFromText() { if (this.TextBoxItem.Text == "") { return 0m; } return base.GetValueFromText(); } public override bool Validate() { if (!this.NullableValue.HasValue) { this.TextBoxItem.Text = ""; return true; } this.TextBoxItem.Text = this.GetTextFromNumber(this.NullableValue.HasValue ? this.internalValue : 0m, this.Hexadecimal, this.ThousandsSeparator, this.DecimalPlaces); return true; } private string GetTextFromNumber(decimal num, bool hex, bool thousands, int decimalPlaces) { if (hex) { return string.Format("{0:X}", (long)num); } return num.ToString((thousands ? "N" : "F") + decimalPlaces.ToString(CultureInfo.CurrentCulture), CultureInfo.CurrentCulture); } public override void PerformStep(decimal step) { decimal value = this.GetValueFromText(); try { decimal incValue = value + step; value = incValue; } catch (OverflowException) { } this.NullableValue = this.Constrain(value); this.Validate(); } protected override Type ThemeEffectiveType { get { return typeof(RadSpinElement); } } public event EventHandler NullableValueChanged; protected virtual void OnNullableValueChanged() { if (this.NullableValueChanged != null) { this.NullableValueChanged(this, EventArgs.Empty); } } }
To reproduce: -add RadTimePicker and set its value to null. -click the arrow to open the pop up and notice that clock header used the default general DateTime pattern to display the text (e.g. 9/18/2013 12:00:00 AM), instead of using the short time pattern displayed (e.g. 12:00 AM) Workaround: this.radTimePicker1.Value = null; this.radTimePicker1.TimePickerElement.PopupOpened+=TimePickerElement_PopupOpened; private void TimePickerElement_PopupOpened(object sender, EventArgs e) { this.radTimePicker1.TimePickerElement.PopupContentElement.ClockHeaderElement.Text = DateTime.Now.ToString(this.radTimePicker1.TimePickerElement.Format, this.radTimePicker1.TimePickerElement.Culture); }
To reproduce: - Add a blank mask to a form and set its Mask type to Standard. - Set its mask to "###-##-##"; - Set its PromptChar to a single space. - Now set the caret before the '-' and type a two digits (the first digit is overridden by the second because the caret is not moved properly). Workaround: Subscribe to the following KeyDown event: void box1_KeyDown(object sender, KeyEventArgs e) { int caretPos = this.box1.MaskedEditBoxElement.TextBoxItem.SelectionStart; if ((e.KeyCode != Keys.Left && e.KeyCode != Keys.Right) && (e.KeyCode != Keys.Up && e.KeyCode != Keys.Down)) { if (caretPos < box1.Text.Length && box1.Text[caretPos] == '-') { this.box1.MaskedEditBoxElement.TextBoxItem.SelectionStart++; } } }