2009-04-08 11 views
6

WinForms, .NetFramework 3,5Winforms DataBind a la propiedad Visible del control

¿Hay algún problema conocido cuando enlace de 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 

Intenté 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 de antemano.

+0

cómo se te liga? con un control bindingsource o declaritively? –

+0

@matt - bindingsource –

+0

Esto podría tener algo que ver con esto: http://stackoverflow.com/a/2570153/2455604 – Marwie

Respuesta

3

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 la configuración de la propiedad Habilitado funciona bien.

1

Lo que debe verificar:

  • Asegúrese de que haya creado una instancia de la clase que tiene la propiedad IsRibbonCategory
  • ¿Ha definido el origen de datos de propiedad del origen 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?

+0

He comprobado todos esos, pero no dados. Una pregunta, ¿has probado la vinculación de datos a la propiedad visible y funcionó? –

+0

Sí. VS 2008/Winforms. ¿Qué evento usas para establecer el origen de datos del control de bindingsource? –

+0

El constructor del formulario. –

8

He descubierto que la vida es mejor si supone que la vinculación a la propiedad Visible de un control se rompe, 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 en al menos 2.0).

Creé una clase de utilidad para crear enlaces que, entre otras cosas, me dio un lugar centralizado para agregar una solución temporal. En lugar de crear realmente una unión visible de que hace dos cosas:

  1. Suscribe caso INotifyPropertyChanged.PropertyChanged de la fuente de datos y define el valor visible en su caso, cuando se ha producido el evento.
  2. Establece el valor inicial de Visible de acuerdo con el valor de fuente de datos actual.

Esto requiere un pequeño código de reflexión, pero no estaba tan mal. Es fundamental que no vincule la propiedad Visible y para solucionar el problema o no funcionará.

+6

+1, y aparentemente esto sigue siendo cierto para .NET 4. –

0

Una solución alternativa sería utilizar 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. véase a continuación 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); 
     } 
    } 
} 

}

Cuestiones relacionadas