Disabling Controls when BindingSource.Count == 0

J

jehugaleahsa

Hello:

I am sure this question comes up a lot. I need to disable the controls
on my Windows forms so that when the BindingSource is empty some the
controls bound to it will be disabled.

This will make it clear to the user that they have to create a new
item first before they start working.

This needs to be an easy process because there are many, many forms.
We can't just go through every control and disable it since some
controls need to always be enabled. My hope was to perform the
operation with some sort of binding.

We have considered other options, such as automatically inserting when
the binding source is empty, but that comes with its own set of
problems. We think disabling is probably the most straighforward way
to eliminate the problem.

Any insight would be helpful.

Thanks,
Travis
 
G

G.S.

Hello:

I am sure this question comes up a lot. I need to disable the controls
on my Windows forms so that when the BindingSource is empty some the
controls bound to it will be disabled.

This will make it clear to the user that they have to create a new
item first before they start working.

This needs to be an easy process because there are many, many forms.
We can't just go through every control and disable it since some
controls need to always be enabled. My hope was to perform the
operation with some sort of binding.

We have considered other options, such as automatically inserting when
the binding source is empty, but that comes with its own set of
problems. We think disabling is probably the most straighforward way
to eliminate the problem.

Any insight would be helpful.

Thanks,
Travis

This group is focused on the C# language itself, not WinForms, so
maybe another group may provide better advice, I do remember however
seeing a discussion here in the last month or so about something
similar.

My post then was about disabling a bunch of controls by placing them
in a panel and only disabling the panel.

If I'm not mistaken, you want to look into the events that
BindingSource exposes and handle enable/disable there. If that doesn't
work, then you need to handle individual control's binding event - you
could probably write a single handle and point all relevant controls
to it.
 
G

G.S.

This group is focused on the C# language itself, not WinForms, so
maybe another group may provide better advice, I do remember however
seeing a discussion here in the last month or so about something
similar.

My post then was about disabling a bunch of controls by placing them
in a panel and only disabling the panel.

If I'm not mistaken, you want to look into the events that
BindingSource exposes and handle enable/disable there. If that doesn't
work, then you need to handle individual control's binding event - you
could probably write a single handle and point all relevant controls
to it.- Hide quoted text -

- Show quoted text -

.... something along those lines:
http://www.codeproject.com/KB/vb/DatabindingReadOnlyProps.aspx
 
J

jehugaleahsa

I am sure this question comes up a lot. I need to disable the controls
on my Windows forms so that when the BindingSource is empty some the
controls bound to it will be disabled.
This will make it clear to the user that they have to create a new
item first before they start working.
This needs to be an easy process because there are many, many forms.
We can't just go through every control and disable it since some
controls need to always be enabled. My hope was to perform the
operation with some sort of binding.  [...]

You don't have enough information in your question for us to understand  
exactly what you're doing.  For example, what kind of control are you  
using?  What kind of data source is bound to the control?  Is it always an  
instance of BindingSource?  Or do you bind with other types as well?

Generally speaking, I'm not aware of any particular feature in data  
binding that does exactly that.  But you can easily implement what you're  
asking using the appropriate events on the objects you're dealing with.

In particular, when you create the controls, subscribe a handler to the  
DataSourceChanged event.  In that event, depending on the type of the data  
source, subscribe a handler to the appropriate event (e.g. ListChanged)  
that will enable/disable the control as appropriate for the data.

For example, let's assuming we're binding a BindingSource instance to a  
DataGridView control.  The above might look something like this:

     class Form1 : Form
     {
         public Form1()
         {
             InitializeComponent();

             dataGridView1.DataSourceChanged +=  
dataGridView1_DataSourceChanged;
         }

         private void dataGridView1_DataSourceChanged(object sender,  
EventArgs e)
         {
             DataGridView dgv = (DataGridView)sender;

             if (dgv.DataSource != null)
             {
                 BindingSource source = (BindingSource)dgv.DataSource;

                 source.ListChanged += delegate(object sender,  
ListChangedEventArgs e)
                 {
                     BindingSource source = (BindingSource)sender;

                     dgv.Enabled = source.Count >0;
                 }
             }
         }
     }

The above assumes that if the binding source for a control is changed, the  
source itself is discarded, never used again.  If that assumption isn't 
true, you'll have to include some code to unsubscribe the previous  
BindingSource.ListChanged event handler, to ensure that the control  
doesn't wind up getting enabled or disabled spuriously (or worse, after  
it's been disposed).  This is kind of a pain, because you'd have to keep a  
reference to the previous DataSource, but it's doable and necessary in  
that situation.  (It's unfortunate that the "XXXChanged" events in .NET 
don't include an easy way to get at the old value, but that's what we're  
stuck with).

Pete

Thanks, Pete. That was informative. I kind of took your idea and made
an extender control. However, the dang thing doesn't work, and I can't
figure out why. If this topic is still alive, could you please look
and see. I'd appreciate it.

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using PowerBillingUI.Controls;

namespace PowerBillingUI.Helpers
{
[ProvideProperty("DisableWhenUnbound", typeof(Control))]
public class DisableHelper : Component, IExtenderProvider
{
private class Handlers
{
public ListChangedEventHandler ListChangedHandler;
public EventHandler EnableChangedHandler;
}

private IndirectBindingSource bindingSource; // just think of
this as a BindingSource
private IDictionary<Control, Handlers> listeners;
private bool enabled;

public DisableHelper()
{
listeners = new Dictionary<Control, Handlers>();
}

public bool Enabled
{
get
{
return enabled;
}
set
{
if (bindingSource != null && enabled)
{
foreach (KeyValuePair<Control, Handlers> pair in
listeners)
{
bindingSource.ListChanged -=
pair.Value.ListChangedHandler;
pair.Key.EnabledChanged -=
pair.Value.EnableChangedHandler;
}
}
enabled = value;
if (enabled && bindingSource != null)
{
foreach (KeyValuePair<Control, Handlers> pair in
listeners)
{
bindingSource.ListChanged +=
pair.Value.ListChangedHandler;
pair.Key.EnabledChanged +=
pair.Value.EnableChangedHandler;
}
}
}
}

public IndirectBindingSource BindingSource
{
get
{
return bindingSource;
}
set
{
bindingSource = value;
}
}

public bool CanExtend(object extendee)
{
return extendee is Control;
}

[DefaultValue(false)]
public bool GetDisableWhenUnbound(Control control)
{
return listeners.ContainsKey(control);
}

public void SetDisableWhenUnbound(Control control, bool
disableWhenUnbound)
{
Handlers handlers;
if (!listeners.TryGetValue(control, out handlers))
{
handlers = null;
}
if (handlers != null)
{
if (bindingSource != null)
{
bindingSource.ListChanged -=
handlers.ListChangedHandler;
}
control.EnabledChanged -=
handlers.EnableChangedHandler;
handlers = null;
}
if (disableWhenUnbound)
{
handlers = new Handlers();
handlers.EnableChangedHandler = (EventHandler)
delegate(object sender, EventArgs e)
{
control.Enabled = bindingSource.Count > 0;
};
handlers.ListChangedHandler =
(ListChangedEventHandler)
delegate(object sender, ListChangedEventArgs e)
{
control.Enabled = !control.Enabled; // fires
EnableChangedHandler
};
}
if (handlers == null)
{
listeners.Remove(control);
}
else
{
listeners[control] = handlers;
}
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top