How to map objects with UI - c#

I have following class implementation (not complete, just to give an idea)
public class MySwitch{
Command command = Command.Red;
public Command GetNext() {
command = GetNext(command); // circular enum values
return command;
}
}
public enum Command { Red =0, Blue=1, Green=2}
public class LED {
public void Glow(Command command){
this.setColor(ColorForm(command));
this.Glow();
}
}
public class Commander {
public Commander(LED target, MySwitch source){
this.LED = LED;
this.MySwitch = MySwitch;
}
public void Execute(){
this.LED.Glow(this.MySwitch.GetNext());
}
}
I want these objects to map to UI items. Consider, I have win form app where switch and LED are two panel where I want GDI to draw it.
Issue is what is best way sync objects with UI elements. Options are:
Create UI element inherited with panel and should contains one
instance of object.
Create UI element (say LEDUI) inherited from BO, and should
contain container (panel) to draw and implement draw method using this.Color
(LED for example) - this will lead to file cound 2* BO
Keep UI element and BO separate and let presenter to be bridge
between them.
Implement method on BO itself to render (assuming single UI) on winform. Since
it cannot be added to winform directly, so create a CustomForm
object which allows such elements (assume IMyObj) to be added, and
call CustomFOrm.Render(), which eventually call render method of
all childElements. Pretty same way Form and controls are rendered.
Any other way
In my opinion, point 2 is better way. Please suggest what pros and cons on different way of mapping BO with UI, and how to sync them. Game developers may have better understanding.
EDIT
My mistake, there could be many LED and switches. Each switch may be attached to many LED. Also the classes I have created is independent of UI. I don't expect solution to how to find the control and glow, but what is the best way to implement if you are given these classes and told to make a winform app, assuming u will least touch the classes as well as write minimum code, along with following standard way of UI development

I've always been taught that referencing goes before inheriting, that if you don't have to access protected members of a certain class you better create an object of that type in your class than inherit the whole class (correct me please if im wrong).
in that light option 3 seems best to me.

In C# (well, WinForms) each UI element has a Tag member into which you can put whatever you want. So, when the user presses the 'switch', the code can iterate over the controls looking for controls with a Tag that matches the current selection.
For example, suppose the LED images have the text 'LED=' in their Tag field, then you can write a function to set the glow state:
// example usage: SetGlow ("Red");
void SetGlow (string colour)
{
SetGlow (Controls, colour);
}
void SetGlow (ControlContainer controls, string colour)
{
foreach (Control control in controls)
{
if (control.Tag is a string) // syntax escapes me
{
string tag = (string) control.Tag;
if (tag.StartsWith ("LED="))
{
if (tag == ("LED=" + colour))
{
// enable glow
}
else
{
// disable glow
}
}
}
SetGlow (control.Controls, colour);
}
}

Related

Execute a method from all instances of a class

I am designing a base class for TextForms and derived classes for Labels , Fields, Dialogboxes... etc.
i am using the below code
public class TextForm
{
public void Refresh()
{
}
}
public class Label : TextForms
{
public void Refresh()
{
}
}
and in my program i am instanciating many Labels .. and somewhere i need to call TextForms.Refresh() which must execute all derived classes instances Refresh() method .
i can't imagine how to do?
You can't find all the instances by default. Though, there are a few design patterns that will make it easier for you to do so. There is the Composite Design Pattern Which gives you the ability to add sub components to your components. For example, a Form/Window component will be a container of sub components like Labels and TextFields for example. Then, when you will call Refresh on the container (Form/Window - for example) it can call the Refresh on all of it's sub components.
There is also the Observable Design Pattern which let components register for 'events' (not necessarily implemented via .Net's Events). Then when you call the Refresh method on the observer, it will call the Refresh methods of all the observable's that are registered.
In your question, you write TextForms so I am assuming that this is an object that is an enumerable of some sort.
Liskows substitution principle dictates that if you have a base class of any kind you can always substitute derived classes for the base class
var textForms = new List<TextForm>();
textForms.Add(new Label());
textForms.Add(new TextBox());
so now you can simply iterate through this list as such:
foreach(var textForm in textForms){
((TextForm) textForm).Refresh();
}
You may have to tweak the example a little to get it working, but that is the general answer to your question.
Like m102 said it is unpractical if not impossible to find all instances. However, assuming you use a canvas or page to display your labels on, it is possible to get all the labels in that canvas.
TextForm tf = new TextForm();
foreach (Control ctrl in yourCanvas.Children.OfType<Label>())
{
tf.Refresh();
}
This will retrieve all the controls of type label from the canvas. This will not refresh them all at once.
Note: I do not recommend changing labels that are not visible/onscreen. It would require them to be kept in memory and this is performancewise not advised. Oh and your refresh function has a capital R (This is usually reserved for classes).

Changing a form object's property from a separate class

I'm very new to using C#. If you have ever heard of the Karol the robot program that is written in Java then that's what I'm aiming to build.
But I am stumbling at almost the first hurdle, I want to make a class for Karol (It is just a picture) that can move around the screen in blocks of 32x32 squares.
Trouble is when you create a class you can't access the properties of form objects because they are separate things.
I would like to be able to manipulate form objects from my class but without having to pass the object through the method each time I use it.
Any help is much appreciated.
Do not need to pass a reference of the Form every time. Should be enough to do something like this:
`public class Karol
{
private Form _form=null;
public Karol(Form frm) {
_form = frm;
}
// after use _form inside the functions and properties of the class, where needed
}`
edit
to acces a control data inside a Form it needs to expose or controls itself, like
public Label MyFormLabel {....}
Or expose a functions/properties that sets or gets the data from the control.
public string MyFormLabelText { get{ return label.Text;} set{label.Text = value;}}
If it's just one form object that "Karol" is manipulating, you should be able to pass it to the constructor and save it for use in later member calls. That way you only pass it once at construction time.

Accessing derived class from base class object issue

I have a kind of weird situation ...
I have a User Control in WPF witch in turn has some other User Controls attached to it, then I have a huge C# code file with a big algorithm which needs access to the User Control UI Elements and methods, this hole process works with a Timer which sends data to the C# code file algorithm from the User Control and it needs to return and update the UI elements from the control and also to access it's methods...
Now the thing is I don't want to put this huge algorithm in the codebehind file of my control, instead I would like to access the control's UI elements and declared methods from that code file ...
What I tried so far is to actually derive the code file's class from the User Control I use, this works fine and dandy but to access the derived class I need to create a new object of it and the UI that I get shown does not get updated since it also creates a new base class object I believe ...
so I have something like:
public partial class usrctrlSimulator : UserControl
{
public usrctrlSimulator()
{
this.InitializeComponent();
}
public void StartSimulator()
{
Algorithm = new csAlgorithm();
Algorithm.InitializeSimulator();
timer1.Start();
}
}
public class csAlgorithm : usrctrlSimulator
{
public csAlgorithm()
{
}
public void InitializeSimulator()
{
txtblkSimulatorStatus.Text = "Started"; // this element would be from the user control
}
}
So my question is : how do I call the derived class without instantiating a new object of it, since that will cause a new user control object to be created and the displayed UI will not be updated ... or if I don't derive the Algorithm class, what possibility do I have to access the user control elements and methods ?
If you want to stick with one instance of the control and still have access to the functionality in the derived class then you need to use the derived class as the control. So instead of an instance of usrctrlSimulator, you'd use csAlgorithm everywhere.
However, I'm not sure whether this design is the best approach in your scenario. The algorithm is not really a user control so maybe deriving from usrctrlSimulator is not the ideal option. For example: UserControl has a method called ApplyTemplate(). What would be the meaning of this in csAlgorithm? You can also look at it from a different angle: Would it be reasonable to use csAlgorithm wherever you could use UserControl, e.g. when invoking UserControl.AddLogicalChild(csAlgorithm)?
A different option would be to instantiate the algorithm as a member variable in usrctrlSimulator (composite). In that case you could still use it inside the usrctrlSimulator but you would have a clear separation of two concepts: A UserControl on one hand, and the implementation of an algorithm on the other hand. In addition you could then change either one of them with only limited impact on the other.
In that case your code would look as follows:
public partial class usrctrlSimulator : UserControl
{
public usrctrlSimulator()
{
this.InitializeComponent();
}
public void StartSimulator()
{
_algorithm= new csAlgorithm();
_algorithm.InitializeSimulator();
timer1.Start();
}
private csAlgorithm _algorithm;
}
public class csAlgorithm // not a UserControl anymore
{
public csAlgorithm()
{
}
public void InitializeSimulator()
{
txtblkSimulatorStatus.Text = "Started"; // this element would be from the user control
}
}

C# Drag and Drop - e.Data.GetData using a base class

I am using C# and Winforms 3.5
I have a list of user controls all derived from one base class. These controls can be added to various panels and I'm trying to implement the drag-drop functionality, the problem I'm running in to is on the DragDrop event.
For DragEventArgs e.Data.GetData(typeof(baseClass)) doesn't work. It wants:
e.Data.GetData(typeof(derivedClass1))
e.Data.GetData(typeof(derivedClass2))
etc...
Is there a way I can get around this, or a better way to architect it?
You can wrap the data in a common class. For example, assuming your base class is called DragDropBaseControl
public class DragDropInfo
{
public DragDropBaseControl Control { get; private set; }
public DragDropInfo(DragDropBaseControl control)
{
this.Control = control;
}
}
And then the drag drop can be initiated with the following in the base class
DoDragDrop(new DragDropInfo(this), DragDropEffects.All);
And you can access the data in the drag events using the following
e.Data.GetData(typeof(DragDropInfo));
Have I understood your requirement correctly?
To get the dragged object dynamically, without even knowing its type or its base type, I use this code inside the DragDrop event:
baseClass myObject = (baseClass)e.Data.GetData(e.Data.GetFormats()[0]);
as e.Data.GetFormats()[0] will always hold string representation of the type of the dragged object.
Note that I assumed there's one object was dragged but the idea is the same for multiple dragged objects.
To elaborate on Abdulhameed Shalabi's answer, make sure the object is of the type expected; otherwise an exception will be thrown on the attempt to cast.
One way is a simple try-catch and ignore the drag-drop if the try fails.
try {
baseClass item = (baseClass)e.Data.GetData( e.Data.GetFormats( )[0] );
if (item != null ) { do stuff }
} catch { }

Extending a solution for simple binding to a 'Text property to multiple Controls to handle binding to any Type?

My question is : how to move beyond writing a custom implementation of a technique for databinding multiple controls (controls without built-in DataSource properties), for each possible type of data, to simple properties ... as described and demonstrated in code that follows ... to achieve a more poweful solution that will be independent of whether the binding is to a string, or an int, or other types.
My guess is: this will involve reflection; but, I'm stuck at that point. I'm looking for strategic advice on which "direction" to move next, hints, clues, not a complete code answer, but of course I appreciate all responses, and I'll sure study code if you post code in reply ! Marc Clifton's 2005 article on CodeProject Simple Databinding: appears to demonstrate a reflection based approach: but, honestly, I do not really grok his code, and, in terms of .NET, 2005 is a long time ago.
Background: Partly in response to various SO questions and answers, like: Update Usercontrol on Three Forms: I've evolved a successful technique for databinding text properties of various controls simultaneously to one source defined in a Public class; also been able to "abstract" some of the details of the binding process using a static class that defines one extension method, and two public methods.
I've verifed that TextBoxes on Controls in a "MainForm," TextBoxes on a UserControl on the MainForm, and a TextBox on a second Form opened "independently" (i.e., form2.Parent == null) all update properly (i.e., two-way binding is in effect) from the "DataSource equivalent" public class. Change one: change all.
Code: an instance of this class will supply the target property (theText) for databinding:
public class TextDataBinder
{
public event PropertyChangedEventHandler PropertyChanged;
private string _theText;
public string theText
{
get { return _theText; }
// note : if 'setter is declared 'internal : blocks
// auto-updating when run-time user modifies consumers
// but will still allow update via code
set
{
_theText = value;
OnPropertyChanged(new PropertyChangedEventArgs("theText"));
}
}
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, e);
}
}
}
Code: this static class enables hiding some of the binding process complexity, and allows easy binding to multiple controls:
public static class TextBindingExtender
{
public static TextDataBinder CurrentDataSource;
public static void SetCurrentDataSource(TextDataBinder newCurrentDataSource)
{
CurrentDataSource = newCurrentDataSource;
}
// extension method for Control
public static void AddTextBinding(this Control theControl, string controlPropertyName, string targetPropertyName)
{
theControl.DataBindings.Add(controlPropertyName, CurrentDataSource, targetPropertyName, false, DataSourceUpdateMode.OnPropertyChanged);
}
// bind to all Controls in a List<Control>
public static void AddTextBindings(List<Control> theControls, string controlPropertyName, string targetPropertyName)
{
foreach (Control theControl in theControls)
{
theControl.AddTextBinding(controlPropertyName, targetPropertyName);
}
}
}
How the above classes are used (in a Form Load event) :
// create a new TextDataBinder
TextBindingExtender.CurrentDataSource = new TextDataBinder();
// bind to multiple textboxes, label, on a UserControl, on another Form, etc.
TextBindingExtender.AddTextBindings(new List<Control> { textBox1, textBox2, userControl11.tb, label1, instanceOfForm2.tb }, "Text", "theText");
// test assigning some initial text to the bound property
TextBindingExtender.CurrentDataSource.theText = "some initial text";
It really depends what you want to do; but ultimately common data-binding (for simple properties, done manually) consists of:
obtaining a property; preferably via TypeDescriptor.GetProperties(obj)[propName], giving you an abstraction (PropertyDescriptor)
asking the property if it is read-only (.IsReadOnly)
obtain (or set) the value (.GetValue(), .SetValue())
asking it for a converter to format / parse the value (.Converter, .ConvertFromString(), .ConvertToString()) THIS is a key bit that means you don't have to worry about what the data type is
asking it for the caption (.DisplayName, or .Name if that it empty/null)
asking it if it supports property-specific notification (.SupportsChangeEvents)
asking it to add/remove a change handler (.AddValueChanged(), .RemoveValueChanged())
you might also want to look at whether the object supports centralised notification (look for INotifyPropertyChanged)
If you might be binding to a list rather than a single object:
- the list might be abstracted behind IListSource
- the list might have custom properties, so check for ITypedList
- otherwise, identify the Type of the items and use TypeDescriptor.GetProperties(type)
- you need to consider a "currency manager" (i.e. should all the things bound to the same list be pointing to the same record in the list all the time)
There are also things like ICustomTypeDescriptor and TypeDescriptionProvider to consider, but most of the time TypeDescriptor handles this for you automatically.
As you can see - lots of things to think about! Lots of work... the one thing that you don't have to do is reflection; this is abstracted behind PropertyDescriptor. The reason for this is that not all data is static-typed; think about DataTable - the columns (which map to bindable data properties) are not fixed at compile-time, so reflection isn't appropriate. Likewise, some other types have custom "property bag" implementations. PropertyDescriptor lets your code handle either dynamic (not in the 4.0 sense) and reflective properties identically. It also works nicely with things like "HyperDescriptor", another property customisation.

Categories

Resources