Copy of a control

  • Thread starter Thread starter Andi Wolf
  • Start date Start date
A

Andi Wolf

Hello,

is there any simple posibility to have a control on 2 diferent tabs of a
tabcontrol without synchronizing? I want to have e.g. a checkbox with the
same label and functionality on two different possitions (e.g. on two
different tabs of a tabcontrol). If I check the first the second sould be
checked too. Adding the same control to each of the tabs dosn't work,
because only the last add to a control will have the checkcontrol the other
additions are deleated. The only two solutions I found jet were
synchronizing 2 checkboxes (event checkbox_1 checked will check the second
and reverse) wich isn't a nice solution. The other one would be to catch the
tab changed event and add the checkbox control to the selected tab each time
the tabcontrol changes.
Are there any better posibilities?

regards Andi
 
Perhaps data-bind the two check-boxes to a single object property that
supports notifications, and let the bindings do some work? Let me know
if you need more detail.

Marc
 
What the heck ;-p

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections.Generic;
static class Program {
static void Main() {
Application.EnableVisualStyles();
using (DemoForm form = new DemoForm()) {
Application.Run(form);
}
}
}
sealed class DemoForm : Form {
private void AddCheckbox(string caption) {
CheckBox cb = new CheckBox();
cb.Dock = DockStyle.Top;
cb.Text = caption;
cb.DataBindings.Add("Checked", sync, "Enabled",true,
DataSourceUpdateMode.OnPropertyChanged);
Controls.Add(cb);
}
private readonly DummySync sync = new DummySync();

protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
AddCheckbox("Bing");
AddCheckbox("Bang");
AddCheckbox("Bong");
}
private sealed class DummySync : INotifyPropertyChanged {
private bool enabled;
public bool Enabled {
get { return enabled; }
set { UpdateField(ref enabled, value, "Enabled"); }
}
private void UpdateField<T>(ref T field, T value, string
propertyName) {
if (EqualityComparer<T>.Default.Equals(field, value))
return;
field = value;
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new
PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
 
Marc,
That is the best kind of answer - code that works. (This bit sounds
like sarcasm, but it isnt...) And without comments - yes we still have
to do some work to 'find out what it all means', but we can get a
working program and then understand it/modify it later.

Maximum respect.
 
Allow me to annotate:

The DummySync class exposes a property, "Enabled", that supports full
data binding - primarily by correctly implementing the
INotifyPropertyChanged interface : whenever the property changes, it
notifies any interested parties (via the event), telling them what
changed.

We create a selection of check-boxes, and tell them to bind their
"Checked" property to the "Enabled" property on a common instance of
DummySync (this "common instance" is important, as in this case you
want all the checkboxes to agree on whether they are checked). This
binding (provided by the framework) does 4 things:
* initally, it will query the "Enabled" value of the common instance
and set "Checked" accordingly
* it subsribes to change notification on the common instance
* when the notification is triggered it re-reads the value
* when the Control's own property is changed directly, it updates the
common instance (indirectly causing the other controls to update
themselves)

This pattern is very useful for abstracting "what features must the UI
offer" from "what must the UI look like"; you can have, for instance,
a SystemOptions class with various checkboxes, textboxes, etc - and by
simply using data-binding you don't need to do a lot of manual "read
the 17 settings from the UI"; additionally, you can easily swap out
the UI (perhaps to use WPF) without having to make major code changes.

Directly linking to the CheckedChanged event-handlers of each control
and updating the siblings would, arguably, work equally - but for my
money the above is quite elegant and (at the minimum) worthy of
consideration.

Marc
 
Thank you, very nice pice of code. Is there any posibility to use this with
buttons too (click event and enable / disable)?

regards Andi
 
This code snippet is pretty much textbook "observer" pattern (mvp too?
I'm not a comp-sci buff); you should be able to use it for any
bindable/browsable property pair, which means most of them. I'm 99%
sure you can sink it to the "Enabled" property on a button - however,
there is no suitable property that gets set automatically on click, so
you'd have to code something. Some types (ToolStripMenuItem for
example) have suitable-looking properties (i.e. Checked when combined
with CheckOnClick = true), but aren't bindable... it doesn't fit every
situation, but is quite tidy most of the time.

Marc
 

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

Back
Top