/// <summary> /// Performs custom actions and raises the <see cref="E:System.Windows.Forms.Control.Layout"></see> event</summary> /// <param name="levent">A <see cref="T:System.Windows.Forms.LayoutEventArgs"></see> that contains the event data</param> protected override void OnLayout(LayoutEventArgs levent) { if (m_context != null) { int x = 1; int width = base.Width; UITypeEditor editor = WinFormsPropertyUtils.GetUITypeEditor(m_descriptor, this); if (editor != null) { if (editor.GetPaintValueSupported(this)) { x += PaintRectTextOffset; } m_textBox.Left = x; m_textBox.Width = width - x - m_editButton.Width; } else { // no editor, use text box and type converters m_textBox.Left = x; m_textBox.Width = width - x; } } base.OnLayout(levent); }
private void OpenDropDownEditor() { if (m_isEditing) { return; } try { m_isEditing = true; object oldValue, value; var oldContext = m_context; // Alan Beckus: save references to all the required objects to perform the transaction. // Because EditValue(...) enters modal loop using Application.DonEvent() // consequently selectedObjects, transaction and event m_context itself can change // before returning from EditValue(...). // note: previous attempt to solve this issue was to cache selected objects inside // m_context but it failed to solve the issue because the cache was cleared // by PropertyView before it can be used. List <object> selection = new List <object>(m_context.SelectedObjects); var transactionContext = m_context.TransactionContext; var descriptor = m_context.Descriptor; oldValue = m_context.GetValue(); UITypeEditor editor = WinFormsPropertyUtils.GetUITypeEditor(m_descriptor, this); // Bring up the editor which can cause Bind() to be called, so make sure that we use the // correct context and selection after this EditValue call. value = editor.EditValue(this, this, oldValue); transactionContext.DoTransaction(delegate { foreach (object selectedObject in selection) { PropertyUtils.SetProperty(selectedObject, descriptor, value); } }, string.Format("Edit: {0}".Localize(), descriptor.DisplayName)); // notify that we just changed a value NotifyPropertyEdit(oldValue, value); // Refresh text box, paint rect if (oldContext == m_context) { SetTextBoxFromProperty(); EnableTextBox(); } Invalidate(); } finally { m_isEditing = false; } }
private void OpenDropDownEditor() { try { m_isEditing = true; PropertyEditorControlContext oldContext = m_context; object oldValue, value; try { // Certain property editing controls like the FlagsUITypeEditor's private CheckedListBox will // not lose focus until the user clicks away, and the user's click may change the // PropertyEditorControlContext's selection, so let's temporarily freeze the selection. oldContext.CacheSelection(); oldValue = m_context.GetValue(); UITypeEditor editor = WinFormsPropertyUtils.GetUITypeEditor(m_descriptor, this); // Bring up the editor which can cause Bind() to be called, so make sure that we use the // correct context and selection after this EditValue call. value = editor.EditValue(this, this, oldValue); oldContext.SetValue(value); } finally { oldContext.ClearCachedSelection(); } // notify that we just changed a value NotifyPropertyEdit(oldValue, value); // Refresh text box, paint rect if (oldContext == m_context) { SetTextBoxFromProperty(); EnableTextBox(); } Invalidate(); } finally { m_isEditing = false; } }
/// <summary> /// Draws the property editing representation, in the same way that the control /// presents the property in the GUI. Use this method to draw inactive properties /// when multitasking a single PropertyEditingControl.</summary> /// <param name="descriptor">Property descriptor</param> /// <param name="context">Type descriptor context</param> /// <param name="bounds">Bounds containing graphics</param> /// <param name="font">Font to use for rendering property text</param> /// <param name="brush">Brush for rendering property text</param> /// <param name="g">Graphics object</param> public static void DrawProperty( PropertyDescriptor descriptor, ITypeDescriptorContext context, Rectangle bounds, Font font, Brush brush, Graphics g) { object owner = context.Instance; if (owner == null) { return; } UITypeEditor editor = WinFormsPropertyUtils.GetUITypeEditor(descriptor, context); if (editor != null) { if (editor.GetPaintValueSupported(context)) { object value = descriptor.GetValue(owner); Rectangle paintRect = new Rectangle( bounds.Left + 1, bounds.Top + 1, PaintRectWidth, PaintRectHeight); editor.PaintValue(new PaintValueEventArgs(context, value, g, paintRect)); bounds.X += PaintRectTextOffset; bounds.Width -= PaintRectTextOffset; g.DrawRectangle(SystemPens.ControlDark, paintRect); } } string valueString = PropertyUtils.GetPropertyText(owner, descriptor); bounds.Height = font.Height; if (s_textFormat.CustomFlags == CustomStringFormatFlags.TrimLeftWithEllipses) { valueString = TrimStringLeftWithEllipses(valueString, bounds, font, g); } g.DrawString(valueString, font, brush, bounds, s_textFormat.Format); }
/// <summary> /// Binds the control to a property and owner</summary> /// <param name="context">Context for property editing control</param> public void Bind(PropertyEditorControlContext context) { if (m_textBox.Focused) { Flush(); } m_context = context; m_descriptor = m_context.Descriptor; bool visible = m_context != null; base.Visible = visible; if (visible) { SetTextBoxFromProperty(); bool editButtonVisible = false; if (!m_context.IsReadOnly) { UITypeEditor editor = WinFormsPropertyUtils.GetUITypeEditor(m_descriptor, this); if (editor != null) { editButtonVisible = true; m_editButton.Modal = (editor.GetEditStyle(this) == UITypeEditorEditStyle.Modal); } } m_editButton.Visible = editButtonVisible; // a standard set of values that can be picked from a list, like enum (but only if we're not readonly) if (!m_context.IsReadOnly && (m_descriptor.Converter != null)) { TypeDescriptorContext tdcontext = new TypeDescriptorContext(m_context.LastSelectedObject, m_descriptor, null); if (m_descriptor.Converter.GetStandardValuesExclusive(tdcontext)) { // this will redraw the control before we get to the invalidate below m_textBox.AutoCompleteMode = AutoCompleteMode.None; m_textBox.AutoCompleteCustomSource.Clear(); AutoCompleteStringCollection standardVals = new AutoCompleteStringCollection(); ICollection values = m_descriptor.Converter.GetStandardValues(tdcontext); foreach (object item in values) { standardVals.Add(item.ToString()); } m_textBox.AutoCompleteCustomSource = standardVals; // this will redraw the control before we get to the invalidate below m_textBox.AutoCompleteSource = AutoCompleteSource.CustomSource; m_textBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend; } else { // this will redraw the control before we get to the invalidate below m_textBox.AutoCompleteMode = AutoCompleteMode.None; m_textBox.AutoCompleteSource = AutoCompleteSource.None; m_textBox.AutoCompleteCustomSource.Clear(); } } else { // this will redraw the control before we get to the invalidate below m_textBox.AutoCompleteMode = AutoCompleteMode.None; m_textBox.AutoCompleteSource = AutoCompleteSource.None; m_textBox.AutoCompleteCustomSource.Clear(); } PerformLayout(); Invalidate(); } }
/// <summary> /// Gets a UITypeEditor for editing the property</summary> /// <returns>UITypeEditor for editing the property</returns> public UITypeEditor GetUITypeEditor() { UITypeEditor editor = WinFormsPropertyUtils.GetUITypeEditor(m_descriptor, this); return(editor); }