Post by Arne VajhøjPost by x***@y.comPost by Arne VajhøjPost by x***@y.comSay I have a form with several controls, text boxes, check boxes,
radio buttons, etc.
The form is shown in two modes, when it is editable and when it is
read ony.
In read only mode I can of course disable the controls but they have
that ugly greyed out washed up look.
In VB6 I would put all the controls inside a frame without border and
without caption, and I would just enable/disable the frame.
The controls would look exactly the same but in one case they are
editable and in the other they are not.
I tries this in C# with a group box/panel but it doesn't work.
The controls inside the disabled group box/panel are disabled but
they have the ugly greyed out look.
Is there a trick you can use in C# to achieve this?
I don't know if there is anything built-in, but you could
always subclass the controls and have the subclass have a bool
property and have event handlers test on that property. Yes - it
requires some upfront work, but when done, then it should be
easy using.
I found some examples that do this using subclass etc.
I was looking for something simple.
It is not that bad. Just some upfront work and then you can
relative easy use that work in the application.
Here is a version with even less code to change (but also a bit
of reflection):
using System;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
namespace E
{
public interface ISoftEnableable
{
bool SoftEnabled { get; set; }
void Fix();
}
public class SoftEnableableTextBox : TextBox, ISoftEnableable
{
public bool SoftEnabled { get; set; }
public void Fix()
{
KeyPress += SoftEnableUtils.SpecialHandlingText;
}
}
public class SoftEnableableButton : Button, ISoftEnableable
{
public bool SoftEnabled { get; set; }
public void Fix()
{
SoftEnableUtils.Fix(this, "Click");
}
}
internal class SoftEnableEventHandlerWrapper
{
private EventHandler eh;
internal SoftEnableEventHandlerWrapper(EventHandler eh)
{
this.eh = eh;
}
internal void InvokeConditionally(object sender, EventArgs e)
{
if(sender is ISoftEnableable)
{
if(((ISoftEnableable)sender).SoftEnabled)
{
eh(sender, e);
}
}
else
{
throw new InvalidOperationException("Can not wrap class
not implementing ISoftEnableable: " + sender.GetType().FullName);
}
}
}
public static class SoftEnableUtils
{
internal static EventHandler SoftEnableWrap(EventHandler eh)
{
return (new
SoftEnableEventHandlerWrapper(eh)).InvokeConditionally;
}
internal static void SpecialHandlingText(object sender,
KeyPressEventArgs e)
{
if(sender is ISoftEnableable)
{
if(!((ISoftEnableable)sender).SoftEnabled)
{
e.Handled = true;
}
}
else
{
throw new InvalidOperationException("Can not do text
handling for class not implementing ISoftEnableable: " +
sender.GetType().FullName);
}
}
internal static void Fix(Control c, string evtnam)
{
EventInfo ei = typeof(Control).GetEvent(evtnam);
FieldInfo fi = typeof(Control).GetField("Event" + ei.Name,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance |
BindingFlags.Static);
PropertyInfo pi = typeof(Control).GetProperty("Events",
BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList ehl = (EventHandlerList)pi.GetValue(c, null);
foreach(EventHandler eh in
ehl[fi.GetValue(c)].GetInvocationList())
{
ei.RemoveEventHandler(c, eh);
ei.AddEventHandler(c, SoftEnableWrap(eh));
}
}
public static void Fix(this Panel p)
{
foreach(Control c in p.Controls)
{
if(c is ISoftEnableable)
{
((ISoftEnableable)c).Fix();
}
}
}
public static void SoftEnable(this Panel p, bool enabled)
{
foreach(Control c in p.Controls)
{
if(c is ISoftEnableable)
{
((ISoftEnableable)c).SoftEnabled = enabled;
}
}
}
}
public partial class MainForm
{
private CheckBox checkBox1;
private Panel panel1;
private TextBox textBox1;
private Button button1;
private void InitializeComponent()
{
checkBox1 = new CheckBox();
panel1 = new Panel();
textBox1 = new SoftEnableableTextBox(); // <----
button1 = new SoftEnableableButton(); // <----
panel1.SuspendLayout();
SuspendLayout();
//
checkBox1.Location = new Point(25, 25);
checkBox1.Size = new Size(250, 25);
checkBox1.Text = "Enabled";
checkBox1.Click += Toggle; // <----
Controls.Add(checkBox1);
//
panel1.Location = new Point(25, 75);
panel1.Size = new Size(250, 150);
Controls.Add(panel1);
//
textBox1.Location = new Point(0, 0);
textBox1.Multiline = true;
textBox1.Name = "textBox1";
textBox1.Size = new Size(250, 100);
panel1.Controls.Add(textBox1);
//
button1.Location = new Point(0, 125);
button1.Size = new Size(250, 25);
button1.Text = "Test";
button1.Click += Test;
panel1.Controls.Add(button1);
//
ClientSize = new Size(300, 250);
Text = "Demo";
ResumeLayout(false);
panel1.Fix(); // <----
panel1.SoftEnable(false); // <----
}
protected void Test(object sender, EventArgs e)
{
MessageBox.Show(textBox1.Text);
}
protected void Toggle(object sender, EventArgs e)
{
panel1.SoftEnable(checkBox1.Checked);
}
}
}
Arne