Winforms DataBind a la propiedad visible de Control
data-binding .net-3.5 (4)
WinForms, .NetFramework 3.5
¿Hay algún problema conocido cuando se vinculan datos a la propiedad visible de un control?
El control NO siempre es visible independientemente de mi propiedad.
Public ReadOnly Property IsRibbonCategory() As Boolean
Get
Return True
End Get
End Property
Probé la propiedad de texto del control y otras propiedades, y parecen funcionar correctamente.
Estoy tratando de establecer la propiedad visible de un Panel.
Usando un BindingSource.
Thx por adelantado.
Cosas para verificar:
- Asegúrese de haber instanciado la clase que tiene la propiedad IsRibbonCategory
- ¿Estableció el origen de datos de la propiedad de la fuente de enlace a la instancia de la clase
- El modo de actualización del origen de datos debe estar en "en validación"
- Asegúrese de que no configuró la propiedad visible manualmente en falso en el control
Espero que ayude. ¿Puedes publicar más código?
Solución alternativa: establezca la propiedad Visible en el evento BindingComplete.
Tuve el mismo problema al establecer la propiedad Visible de una etiqueta; siempre permanece en falso, aunque configurar la propiedad Habilitado funciona bien.
Descubrí que la vida es mejor si se supone que el enlace a la propiedad Visible de un control está roto, a pesar de que a veces funciona. Consulte http://support.microsoft.com/kb/327305 , que dice tanto (y aunque el artículo de KB se aplica a .NET 1.0 y 1.1, todavía parece ser un problema al menos en 2.0).
Creé una clase de utilidad para crear enlaces que, entre otras cosas, me dio un lugar centralizado para agregar una solución alternativa. En lugar de crear realmente un enlace en Visible, hace dos cosas:
- Se suscribe al evento INotifyPropertyChanged.PropertyChanged de la fuente de datos y establece el valor Visible según corresponda cuando se produce el evento.
- Establece el valor inicial de Visible de acuerdo con el valor de la fuente de datos actual.
Esto requirió un pequeño código de reflexión, pero no fue tan malo. Es fundamental que no vincule la propiedad Visible y no trabaje, o no funcionará.
Una solución alternativa sería usar un Componente para enlazar datos a la propiedad de visibilidad de un control en lugar de vincularlo directamente a la propiedad de visibilidad del control. Vea el siguiente código:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public class ControlVisibilityBinding : Component
{
private static readonly object EventControlChanged = new object();
private static readonly object EventVisibleChanged = new object();
private System.Windows.Forms.Control _control;
private bool _visible = true;
public event EventHandler VisibleChanged
{
add { Events.AddHandler(EventVisibleChanged, value); }
remove { Events.RemoveHandler(EventVisibleChanged, value); }
}
public event EventHandler ControlChanged
{
add { Events.AddHandler(EventControlChanged, value); }
remove { Events.RemoveHandler(EventControlChanged, value); }
}
public ControlVisibilityBinding()
{
}
public ControlVisibilityBinding(IContainer container)
{
container.Add(this);
}
[DefaultValue(null)]
public System.Windows.Forms.Control Control
{
get { return _control; }
set
{
if(_control == value)
{
return;
}
WireControl(_control, false);
_control = value;
if(_control != null)
{
_control.Visible = _visible;
}
WireControl(_control, true);
OnControlChanged(EventArgs.Empty);
OnVisibleChanged(EventArgs.Empty);
}
}
[DefaultValue(true)]
public bool Visible
{
get { return _visible; }
set
{
if(_visible != value)
{
_visible = value;
}
if(Control != null)
{
Control.Visible = _visible;
}
OnVisibleChanged(EventArgs.Empty);
}
}
private void WireControl(Control control, bool subscribe)
{
if(control == null)
{
return;
}
if(subscribe)
{
control.VisibleChanged += Control_VisibleChanged;
}
else
{
control.VisibleChanged -= Control_VisibleChanged;
}
}
private void Control_VisibleChanged(object sender, EventArgs e)
{
OnVisibleChanged(EventArgs.Empty);
}
protected virtual void OnVisibleChanged(EventArgs e)
{
EventHandler subscribers = (EventHandler)Events[EventVisibleChanged];
if(subscribers != null)
{
subscribers(this, e);
}
}
protected virtual void OnControlChanged(EventArgs e)
{
EventHandler subscribers = (EventHandler)Events[EventControlChanged];
if(subscribers != null)
{
subscribers(this, e);
}
}
}
static class Program
{
[STAThread]
static void Main()
{
using(Form form = new Form())
using(FlowLayoutPanel groupBoxLayoutPanel = new FlowLayoutPanel())
using(RadioButton visibleButton = new RadioButton())
using(RadioButton hiddenButton = new RadioButton())
using(GroupBox groupBox = new GroupBox())
using(Label text = new Label())
using(ControlVisibilityBinding visibilityBinding = new ControlVisibilityBinding())
using(TextBox inputTextBox = new TextBox())
{
groupBoxLayoutPanel.Dock = DockStyle.Fill;
groupBoxLayoutPanel.FlowDirection = FlowDirection.LeftToRight;
groupBoxLayoutPanel.AutoSize = true;
groupBoxLayoutPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
visibleButton.Text = "Show Label";
visibleButton.AutoSize = true;
hiddenButton.Text = "Hide Label";
hiddenButton.AutoSize = true;
groupBoxLayoutPanel.Controls.Add(visibleButton);
groupBoxLayoutPanel.Controls.Add(hiddenButton);
inputTextBox.Text = "Enter Label Text Here";
inputTextBox.Dock = DockStyle.Top;
groupBox.AutoSize = true;
groupBox.AutoSizeMode = AutoSizeMode.GrowAndShrink;
groupBox.Controls.Add(groupBoxLayoutPanel);
groupBox.Dock = DockStyle.Fill;
text.AutoSize = true;
text.ForeColor = Color.Red;
text.Dock = DockStyle.Bottom;
text.BorderStyle = BorderStyle.FixedSingle;
text.Font = new Font(text.Font.FontFamily, text.Font.Size * 1.25f, FontStyle.Bold | FontStyle.Italic);
text.DataBindings.Add("Text", inputTextBox, "Text", true, DataSourceUpdateMode.Never);
visibilityBinding.Control = text;
visibleButton.DataBindings.Add("Checked", visibilityBinding, "Visible", true, DataSourceUpdateMode.OnPropertyChanged);
Binding binding = hiddenButton.DataBindings.Add("Checked", visibilityBinding, "Visible", true, DataSourceUpdateMode.OnPropertyChanged);
ConvertEventHandler invertConverter = (sender, e) => e.Value = !((bool)e.Value);
binding.Format += invertConverter;
binding.Parse += invertConverter;
form.Controls.Add(inputTextBox);
form.Controls.Add(text);
form.Controls.Add(groupBox);
Application.Run(form);
}
}
}
}