Benutzer mit den meisten Antworten
Checkbox auf Readonly setzen

Frage
-
Hallo Forum,
ein Textfeld kann via ReadOnly, bzw. Locked vor Veränderung geschützt werden.
Die Checkbox hat dagegen nur das Property Locked.
Warum gibt es für die Checkbox kein ReadOnly, bzw. was ist bei einem Textfeld die "bessere" Variante zum Schützen eines Feldes.
Besten Dank vorab!
Ciao, Alberto
Antworten
-
Hallo Alberto
hängt sehr vom Szenario ab, aber in einigen Fällen könnte man uva auch einen Ansatz sehen in:
CheckBox.AutoCheck
http://msdn.microsoft.com/de-de/library/system.windows.forms.checkbox.autocheck(VS.80).aspx- Als Antwort vorgeschlagen Thorsten DörflerEditor Sonntag, 28. November 2010 19:19
- Als Antwort markiert Robert BreitenhoferModerator Freitag, 3. Dezember 2010 13:34
-
Hallo Alberto,
ja, by design, aber wenn man es trotzdem machen möchte, ist das auch möglich.
Zum einen kannst Du für Dich prüfen, ob es nicht einfach für Dich ausreichend ist, die Enabled-Eigenschaft auf false festzusetzen.
Will man trotzdem flexibel den Fokus und Click-Handling und andere Dinge ermöglichen/erhalten, kann die folgende Methode (grober Pseudo-Code) hilfreich sein:using System.Drawing; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; public partial class ReadOnlyCheckBox : CheckBox { int abstandOben; Point glyphLocation; protected override void OnPaint(PaintEventArgs e) { abstandOben = (ClientRectangle.Height - Font.Height) / 2; glyphLocation = new Point(0, abstandOben); Rectangle rec = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y + abstandOben, e.ClipRectangle.Width, e.ClipRectangle.Height - abstandOben); var pe = new PaintEventArgs(e.Graphics, rec); base.OnPaintBackground(e); if (this.Checked) { CheckBoxRenderer.DrawCheckBox(pe.Graphics, glyphLocation, e.ClipRectangle, Text, Font, Focused, CheckBoxState.CheckedDisabled); } else { CheckBoxRenderer.DrawCheckBox(pe.Graphics, glyphLocation, e.ClipRectangle, Text, Font, Focused, CheckBoxState.UncheckedDisabled); } pe.Dispose(); } }
-----------------
Aufruf in der Form:
private void Form1_Load(object sender, EventArgs e) { ReadOnlyCheckBox cb = new ReadOnlyCheckBox(); cb.Text = "ReadOnly-Checkbox"; cb.Width = 150; cb.Location = new Point(50, 50); Controls.Add(cb); }
ciao Frank- Als Antwort vorgeschlagen Frank Dzaebel Sonntag, 28. November 2010 19:48
- Nicht als Antwort vorgeschlagen Thorsten DörflerEditor Sonntag, 28. November 2010 19:59
- Als Antwort vorgeschlagen Frank Dzaebel Sonntag, 28. November 2010 20:40
- Als Antwort markiert Robert BreitenhoferModerator Freitag, 3. Dezember 2010 13:34
-
Hallo Alberto,eine mögliche Implementierung, neben dem von Thomas vorgeschlagenen AutoCheck,
wäre OnClick zu unterdrücken.
In der folgendn Implementierung entferne ich, zudem das Steuerlement aus der Tabulator-Reihenfolge,
wenn es auf ReadOnly gesetzt wird, das wäre dabei optional:Gruß Elmarusing System; using System.ComponentModel; using System.Windows.Forms; namespace ElmarBoye.Samples.Forms { public class ReadOnlyCheckBox : System.Windows.Forms.CheckBox { private readonly static object ReadOnlyEventKey = new object(); private bool readOnly; public ReadOnlyCheckBox() { this.ReadOnly = true; } #region ReadOnly Property [Category("Behavior"), Description("Setzt die CheckBox auf schreibgeschützt. Vorgabe ist wahr."), DefaultValue(true), RefreshProperties(RefreshProperties.Repaint)] public bool ReadOnly { get { return this.readOnly; } set { if (this.ReadOnly != value) { this.readOnly = value; // Optional: Aus der Tab-Reihenfolge entfernen base.SetStyle(ControlStyles.Selectable, !value); OnReadOnlyChanged(EventArgs.Empty); } } } protected virtual void OnReadOnlyChanged(EventArgs e) { var handler = base.Events[ReadOnlyEventKey] as EventHandler; if (handler != null) handler(this, e); } public event EventHandler ReadOnlyChanged { add { base.Events.AddHandler(ReadOnlyEventKey, value); } remove { base.Events.RemoveHandler(ReadOnlyEventKey, value); } } #endregion ReadOnly Property /// <summary> /// Wenn ReadOnly aktiv, wird das Click Ereignis (und Basisbehandlung der Standard-CheckBox) unterdrückt. /// </summary> protected override void OnClick(EventArgs e) { if (!this.ReadOnly) base.OnClick(e); } } }
- Als Antwort markiert Robert BreitenhoferModerator Freitag, 3. Dezember 2010 13:38
Alle Antworten
-
Hallo Alberto
hängt sehr vom Szenario ab, aber in einigen Fällen könnte man uva auch einen Ansatz sehen in:
CheckBox.AutoCheck
http://msdn.microsoft.com/de-de/library/system.windows.forms.checkbox.autocheck(VS.80).aspx- Als Antwort vorgeschlagen Thorsten DörflerEditor Sonntag, 28. November 2010 19:19
- Als Antwort markiert Robert BreitenhoferModerator Freitag, 3. Dezember 2010 13:34
-
Hallo Alberto,
ja, by design, aber wenn man es trotzdem machen möchte, ist das auch möglich.
Zum einen kannst Du für Dich prüfen, ob es nicht einfach für Dich ausreichend ist, die Enabled-Eigenschaft auf false festzusetzen.
Will man trotzdem flexibel den Fokus und Click-Handling und andere Dinge ermöglichen/erhalten, kann die folgende Methode (grober Pseudo-Code) hilfreich sein:using System.Drawing; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; public partial class ReadOnlyCheckBox : CheckBox { int abstandOben; Point glyphLocation; protected override void OnPaint(PaintEventArgs e) { abstandOben = (ClientRectangle.Height - Font.Height) / 2; glyphLocation = new Point(0, abstandOben); Rectangle rec = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y + abstandOben, e.ClipRectangle.Width, e.ClipRectangle.Height - abstandOben); var pe = new PaintEventArgs(e.Graphics, rec); base.OnPaintBackground(e); if (this.Checked) { CheckBoxRenderer.DrawCheckBox(pe.Graphics, glyphLocation, e.ClipRectangle, Text, Font, Focused, CheckBoxState.CheckedDisabled); } else { CheckBoxRenderer.DrawCheckBox(pe.Graphics, glyphLocation, e.ClipRectangle, Text, Font, Focused, CheckBoxState.UncheckedDisabled); } pe.Dispose(); } }
-----------------
Aufruf in der Form:
private void Form1_Load(object sender, EventArgs e) { ReadOnlyCheckBox cb = new ReadOnlyCheckBox(); cb.Text = "ReadOnly-Checkbox"; cb.Width = 150; cb.Location = new Point(50, 50); Controls.Add(cb); }
ciao Frank- Als Antwort vorgeschlagen Frank Dzaebel Sonntag, 28. November 2010 19:48
- Nicht als Antwort vorgeschlagen Thorsten DörflerEditor Sonntag, 28. November 2010 19:59
- Als Antwort vorgeschlagen Frank Dzaebel Sonntag, 28. November 2010 20:40
- Als Antwort markiert Robert BreitenhoferModerator Freitag, 3. Dezember 2010 13:34
-
"Alberto Luca" schrieb
Die Checkbox hat dagegen nur das Property Locked.
So eine checkbox ist ja nicht sonderlich kompliziert, die kann man auch selber implementieren, noch dazu wenn man sie nur ReadOnly braucht.
Wie man das macht ist im Thread "Im "set"-Bereich Objekt neu zeichnen, Farbverlaufs-Panel" ausführlich erläutert worden ;-)
Du musst nur die gewünschten Bildchen einblenden. -
Hallo Frank,
Will man trotzdem flexibel den Fokus und Click-Handling und andere Dinge ermöglichen/erhalten, kann die folgende Methode (grober Pseudo-Code) hilfreich sein:
using System.Drawing; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; public partial class ReadOnlyCheckBox : CheckBox
ich vermisse bei Deiner Pseudo-Code Lösung irgendwie den read-only Aspekt, nach dem dem Alberto hier gefragt hat. Das Zeichnen der CheckBox wäre dabei auch noch verbesserungswürdig. So wird der Text unter der CheckBox gezeichnet, wenn diese zu klein ist bzw. mit AutoSize = true; eingesetzt wird. Zieht man sie größer erscheint der Text mittig ausgerichtet. Bei der Standard CheckBox verhält sich das anders. Aber gut, ist ja nur Pseudo-Code.
Thorsten Dörfler
Microsoft MVP Visual Basic
vb-faq.de -
Hallo Thorsten,
die erwähnte Pseudo-CheckBox zeichnet einfach nur ReadOnly. Für mich war es zu trivial, jetzt noch eine ReadOnly-Prop zu machen, die das jeweils auf die eine oder andere Art (base.Paint) umsetzt. Ich denke, Alberto wird es verstehen, dass nur die Essenz dargestellt ist.
Ansonsten wird die CheckBox schon als PseudoCode gut umgesetzt. Es sind aber noch keine Spezialitäten berücksichtigt.
Es ist nur ein Ansatz - Die Size-Geschichten sind alle sehr einfach in den Griff zu bekommen.
Ich habe die Anregung von Linda Liu [Microsoft], in der sie ähnliche Dinge vorschlägt.
ciao Frank -
Hallo U.,
> nicht sonderlich kompliziert ...
na, die hats schon in sich! Die wahren Werte liegen etwas verborgen. Speziell sind Zeichnungs-Aktionen ansich je nach Windows-Einstellung dynamisch. Das sind zum Teil Fadings, die nicht trivial sind.
Es ist in diesem Fall aber gerade noch durch die Hilfsklassen "CheckBoxRenderer.DrawCheckBox" etc. machbar. Mein Pseudo-Beispiel ist ja auch schon nicht ohne, berücksichtigt aber auch noch nicht alle Spezialitäten.
ciao Frank -
Hallo Frank,
Für mich war es zu trivial
darum verstehe ich auch nicht, warum Du es nicht im Pseudo-Code berücksichtigt hast. Thomas hat ja schon den richtigen Weg aufgezeigt. Solange AutoCheck unberücksichtigt bleibt, ist Dein Beitrag nicht als Lösung/Antwort zu sehen, da die CheckBox weiterhin verändert werden kann.
Anregung von Linda Liu [Microsoft]
Eine Referenz wäre nicht schlecht und erspart anderen das Suchen.
Thorsten Dörfler
Microsoft MVP Visual Basic
vb-faq.de -
"Frank Dzaebel [MVP]" schrieb
nicht sonderlich kompliziert ...
na, die hats schon in sich!
Man blendet bei True das ein Bildchen ein und bei False das andere fertig und das über Setter und Invalidate() wie oben besprochen.
Eine Klasse von Component ableiten, ein Property Value, das e.Graphics liefert der Parameter von Paint - was brauchst Du noch?
Bei der Gelegenheit kann man einen schönen grünen Hacken reinmachen oder einen Roten oder ne Ampel oder was auch immer.
-
Hallo Thorsten,
Das ist Deine Interpretation/Meinung. Ich sehe das als Antwort - mein Ansinnen ist aber hier aber eher Alberto zu helfen. Da ist dieser Weg über den ComboBoxRenderer IMHO der beste. Ich will Dir das auch nicht erklären, sondern Alberto. Wenn "Du" eine Frage hast, stelle sie explizit als Forums-Frage. Ich denke, Alberto wird meinen Quellcode verstehen. Wenn nicht, werde ich "ihm" das erklären.
ciao Frank -
Hallo Frank,
Da ist dieser Weg über den ComboBoxRenderer IMHO der beste.
Nö, eher nicht. Du meinst wohl CheckBoxRenderer. Aber damit wird das Ding nicht read-only, sondern schaut nur anders aus. Darum geht es eigentlich. Du kannst das natürlich gerne anders sehen.
Ich will Dir das auch nicht erklären
Mir musst Du das auch nicht erklären. :D
Wenn "Du" eine Frage hast, stelle sie explizit als Forums-Frage.
Meine Anmerkungen bezogen sich auf Deine Antworten.
Thorsten Dörfler
Microsoft MVP Visual Basic
vb-faq.de -
Hallo U.,
... ich habe ja ein Beispiel mit dem CheckBoxRenderer gemacht. Da kann man es sich es abschauen.
Inwieweit jetzt grün oder rot oder mit Ampel ;-) ja - da ist man dann sehr flexibel, das ist einer der Vorteile dieser Lösung.> Eine Klasse von Component ableiten,
kann es sein, dass Dein Posting ggf. in einen anderen Thread sollte? ;-)
Ich denke, dass die Ableitung von CheckBox schon richtig ist.
ciao Frank -
Thorsten,
wie gesagt, liegst Du meiner Meinung nach fachlich falsch mit Deiner Interpretation.
Aber ich rede da lieber mit Alberto weiter - nicht mit Dir.
Fachlich habe ich Stellung genommen. Das ist in meinem Anfangs-Beitrag zu lesen.
ciao Frank- Bearbeitet Frank Dzaebel Sonntag, 28. November 2010 21:55
-
Hallo Alberto,eine mögliche Implementierung, neben dem von Thomas vorgeschlagenen AutoCheck,
wäre OnClick zu unterdrücken.
In der folgendn Implementierung entferne ich, zudem das Steuerlement aus der Tabulator-Reihenfolge,
wenn es auf ReadOnly gesetzt wird, das wäre dabei optional:Gruß Elmarusing System; using System.ComponentModel; using System.Windows.Forms; namespace ElmarBoye.Samples.Forms { public class ReadOnlyCheckBox : System.Windows.Forms.CheckBox { private readonly static object ReadOnlyEventKey = new object(); private bool readOnly; public ReadOnlyCheckBox() { this.ReadOnly = true; } #region ReadOnly Property [Category("Behavior"), Description("Setzt die CheckBox auf schreibgeschützt. Vorgabe ist wahr."), DefaultValue(true), RefreshProperties(RefreshProperties.Repaint)] public bool ReadOnly { get { return this.readOnly; } set { if (this.ReadOnly != value) { this.readOnly = value; // Optional: Aus der Tab-Reihenfolge entfernen base.SetStyle(ControlStyles.Selectable, !value); OnReadOnlyChanged(EventArgs.Empty); } } } protected virtual void OnReadOnlyChanged(EventArgs e) { var handler = base.Events[ReadOnlyEventKey] as EventHandler; if (handler != null) handler(this, e); } public event EventHandler ReadOnlyChanged { add { base.Events.AddHandler(ReadOnlyEventKey, value); } remove { base.Events.RemoveHandler(ReadOnlyEventKey, value); } } #endregion ReadOnly Property /// <summary> /// Wenn ReadOnly aktiv, wird das Click Ereignis (und Basisbehandlung der Standard-CheckBox) unterdrückt. /// </summary> protected override void OnClick(EventArgs e) { if (!this.ReadOnly) base.OnClick(e); } } }
- Als Antwort markiert Robert BreitenhoferModerator Freitag, 3. Dezember 2010 13:38
-
Hallo Alberto,
Zum Thema CheckBox ist nicht mehr viel zu sagen: Das Setzen von CheckBox.AutoCheck auf false - so wie Thomas das vorgeschlagen hat - verhindert das Aktualisieren von CheckBox.CheckState (sobald der Benutzer auf die CheckBox klickt). Das Aktualisieren von CheckBox.CheckState ist aber weiterhin per Code möglich, genauso wie das auch bei TextBox.ReadOnly = true passieren würde. Insofern sehe auch ich darin eine gute Äquivalenz zu ReadOnly.
Ein Textfeld kann via ReadOnly, bzw. Locked vor Veränderung geschützt werden.
Die Sache mit der "Locked"-Eigenschaft hingegen stimmt so nicht. Diese Eigenschaft gehört eigtl. nicht zum TextBox-Steuerelement (Du kannst sie nicht per Code setzen und es wird kein Code dafür generiert), sondern zur Designzeit-Unterstützung (man findet einen entspr. Eintrag in Form1.resx). Locked bestimmt ob ein Steuerelement während der Designzeit verschoben oder in seiner Größe verändert werden kann (s. System.Windows.Forms.Design.ControlDesigner, der Standarddesigner für alle Controls). Du meintest hier wohl eher die Eigenschaft Control.Enabled.
Gruß
Marcel -
Hallo Elmar,
Deine ReadOnlyCheckBox ist keine Lösung "alleine". Genauso, wie AutoCheck keine Lösung alleine ist. Im Effekt machen es beide Varianten (alleine) nur schlimmer.
Ein gutes UI muss gemäß Windows Vorgaben (Richtlinien) einen ReadOnly Zustand auch visuell anzeigen.
Das ist in meinem Posting sehr gut zu sehen. Der User würde sich berechtigterweise beim Hersteller über solche Dinge beschweren, denn sicher wird man ein nicht möglichen Klick hier mehrheitlich als Bug interpretieren.Allerdings war meine Lösung auch so gedacht, dass eben beliebige Methodik (Property, TAB-Reihenfolge, Fokus, etc.) nach eigenen Wünschen zugefügt werden kann.
Eine Methodik wäre hier zum Beispiel:
[CheckBoxRenderer-Klasse (System.Windows.Forms)]
http://msdn.microsoft.com/de-de/library/system.windows.forms.checkboxrenderer.aspxzusammen mit meinem ReadOnly-OnPaint Quellcode.
Hier wird auch sauberer mit OnMouseDown gearbeitet und weiter auch andere Zustände berücksichtigt, die auch bei Dir fehlen. Das Mouse-Hovering etwa, sollte auch noch sauber berücksichtigt werden, denn hier sollten auch visuelle (ReadOnly) Feedback-Effekte auftreten.
Aber das kommt sehr auf andere Anforderungen an, insbesondere, weil man hier auch ein wenig gegen das vorgesehene Design von Microsoft arbeitet.
Du machst ein "RefreshProperties(RefreshProperties.Repaint)" Attribut .... wieso?, wenn Du eh nicht den visuelle Rendering anpasst?
ciao Frank -
Marcel,
> Insofern sehe auch ich darin eine gute Äquivalenz zu ReadOnly.
es fehlt nur das visuelle Rendering. Deswegen ist ein AutoCheck eher verschlimmernd, weil der User nun (da es wie eine klickbare CheckBox aussieht) von einer normalen CheckBox ausgeht und berechtigterweise draufklicken können möchte. Das gibt garantiert einen Anstieg der Hotline-Aufwände. Sowas muss in gutem Design auch visuell gerendert werden.
MS-Beispiele arbeiten bei CheckBoxRenderern (wie in meinem Lösungs-Beispiel zum Rendering/Zeichnen) meist mit OnMouseDown.
ciao Frank -
Elmar,
wenn Du fachlich dazu nicht Stellung nehmen willst, so ist das in Ordnung - steht Dir frei.
Ich bringe diese Dinge nur an, weil ich denke, dass das in der Entscheidung hilfreich ist.
Ansich ist das Rendering auch IMHO keine Frage, ob Alberto das fragt, sondern dies schreiben Windows-Richtlinien eh vor. Stell Dir mal vor, die TextBox würde beim ReadOnly nicht ~gräulich werden. Die Benutzer würden darüber fluchen und man hätte sein Control im Grunde verschlimmbessert!
Aber gut - ich respektiere, wenn Du Dich dazu nicht äußern willst.
ciao Frank -
Hallo Frank,
> es fehlt nur das visuelle Rendering [...]
Das MSDN-Beispiel zum CheckBoxRenderer verwendet bezeichnenderweise ein von Control (nicht von CheckBox) abgeleitetes Steuerelement. Das macht Sinn, weil CheckBox.CheckState nur drei Zustände unterstützt, wohingegen die CheckBoxState-Enumeration zwölf Member hat. Die zwölf Member von CheckBoxState auf die CheckBox.CheckStates zu mappen und dabei das CheckBox-Control in einem validen internen Zustand zu behalten, ist eine Herausforderung der besonderen Art, da sich nun visuelle Stile (normal, hot, pressed, disabled) zu jedem der CheckStates assoziieren lassen. Das wirft aber Fragen auf: Wie würde man mit einem CheckState.Indeterminate (Häckchen und schattiert) in den verschiedenen visuellen Stilen konsistent umgehen? Und wie sollte man CheckBoxState.UncheckedPressed sinnvollerweise mappen? Und was macht man nur, wenn im OS die visuellen Stile gar nicht aktiviert sind? - Das kann kompliziert und verwirrend und teuer werden (sowohl während der Entwicklung als auch nachher).Gruß
Marcel- Als Antwort vorgeschlagen Marcel RomaModerator Freitag, 3. Dezember 2010 13:41
-
Marcel,
- Die zwölf Member von CheckBoxState auf die CheckBox.CheckStates zu mappen und dabei das CheckBox-Control in einem validen internen Zustand zu behalten, ist eine Herausforderung der besonderen Art,
ja, würde ich im ersten Anlauf auch nicht machen. Deswegen auch erstmal ein rudimentärer Pseudo-Code, der einem den Weg weist.
Deinen aufgeworfenen Fragen sind richtige Anfangs-Überlegungen beim Thema "Custom Rendering". Deswegen würde ich im Anfang auch erstmal pragmatisch vereinfacht implementieren. Oft reichen reduzierte Anforderungen - man will ja vielleicht auch kein Indeterminate etc.. Das kommt dann eben auf Albertos Anforderungen an.
Allgemein sollte am Anfang im Kern ein visuelles ReadOnly-Feedback für den User reichen (wie etwa mit meinem PseudoCode-Beispiel -> KISS), um auch nicht im YAGNI zu enden (was dann, wie Du richtig sagst, auch ggf. zu teuer wird).
ciao Frank