Custom event on object to change button state - c#

I have 3 buttons on my Data Entry form, OK, APPLY, CANCEL.
This form is used to edit a doctor's details, things like first name, phone # etc...
I have one object doctorObj which at any given time is either empty (a new doctor) or an object pulled from a Linq query.
I deep clone the doctorObj to EditCopyDoctor which is of the same type but used for form editing (so if Cancel is hit, the database do not need to update).
What I want to achieve is observe the EditCopyDoctor for changes against the original doctorObj so
If(doctor.Changed() && doctor.IsNotNew)
{
ApplyButton.Enabled = true;
}
else
{
ApplyButton.Enabled = false;
}
So I thought writting an event to trigger when something changed on EditCopyDoctor is the best way to do it but I'm not sure how.
I can of course put the ApplyButton.Enabled code in the TextChanged events from the form but I was wondering if there are any quicker ways to do this, I don't really want to do this as there are 10+ textbox and other controls.

Since your "Doctor" type sounds like it's generated by LINQ to SQL/Entities you should find that it already implements the INotifyPropertyChanged interface. Therefore, you should just need to watch the PropertyChanged event and act accordingly.

Related

c# wpf - Refresh grid when returning from edit window

Good morning,
I wanted to know the best way to refresh a grid after making a change to one of the elements in an edit window.
I have a grid with lets say employees. I pass the employee as reference to the edit window...
EmployeeEdit wEdit = new EmployeeEdit(ref selectedEmployee);
wEdit.Show();
If I delete this employee and come back to the main grid, that employee is still there because the grid has not refreshed (I dont want to do a showdialog).
I was thinking about passing a variable as reference and changing that variable upon deleting an employee. Then, when the original grid got focus, check the variable and refresh the grid if I have to.
This seems like a rigged fix and I wanted to know the most efficient way to do this.
Thank you
You need to subscribe to an event in wEdit object, for example it may have a closing event or a quit event (unfortunately I can't tell from your code).
To subscribe to the event you can write something like this;
EmployeeEdit wEdit = new EmployeeEdit(ref selectedEmployee);
wEdit.Closing += (s, e) =>
{
//place code to refresh your grid here
}
wEdit.Show();
When the event fires it should refresh your grid.

Apply Input Mask for a ToolStripComboBox C#

I was just wondering if anyone has come across how to apply an input mask for a Tool Strip Combo Box in C#?
My drop down box gets populated over time with IP addresses, and I would like to restrict what the users are able to write in (Ex: can only input 3 '.'s, only numbers, etc).
So if anyone is able to help out I would really appreciate it!
Thanks in advance.
Edit
My design has changed so I now need to have a ToolStripComboBox
You could try catching the KeyUp event, then check that the input is valid. If not revert it to the last valid input. You would probably want to do something similar with the Validating event (make sure CausesValidation is true).
Another option would be to create a MaskedTextBox and place it so it covers the text box portion of the drop down menu. You would then need to wire up the events so the two form controls remained synced.
You could also look into the ErrorProvider class.
There are a couple of other ways (like a timer which runs ever .3 seconds), but those are usually performance hogs or difficult to maintain.
Update for regular expression comment:
If I was to do this I might use a regular expression or I might manually parse the string.
Either way the KeyUp and Validating events is where I would check the validation of the control. The KeyUp event gives me the option to check as they type while the Validating event allows me to validate when the control loses focus. Which you use will depend on what you want the user experience to be.
If you do not use the KeyUp event to validate, you could add a timer which runs 5 seconds after the last key press. This way the control would not have to lose focus for the error to show.
Update for edited question and comment:
You could not use Format event as your question was on how to format user input, not how things are added to the list. As such that solution does not work with ToolStripComboBox or with ComboBox.
After reading the documentation for ToolStripControlHost, you might be able to cast ToolStripComboBox to ComboBox. If not then you could use the ToolStripControlHost to place the ComboBox onto your form. - This is incorrect or unnecessary, please see update below the quote.
ToolStripControlHost is the abstract base class for ToolStripComboBox, ToolStripTextBox, and ToolStripProgressBar. ToolStripControlHost can host other controls, including custom controls, in two ways:
Construct a ToolStripControlHost with a class that derives from Control. To fully access the hosted control and properties, you must cast the Control property back to the actual class it represents.
Extend ToolStripControlHost, and in the inherited class's default constructor, call the base class constructor passing a class that derives from Control. This option lets you wrap common control methods and properties for easy access in a ToolStrip.
Use the ToolStripControlHost class to host your customized controls or any other Windows Forms control.
To customize a ToolStripItem, derive from ToolStripControlHost and create a custom implementation. You can override methods such as OnSubscribeControlEvents to handle events raised by the hosted controls, and you can put custom functionality into properties to enhance the hosted control.
Update:
According to the ToolStripComboBox documentation you can access the underlying ComboBox through ToolStripComboBox's ComboBox property.
This is why I usually read the documentation on a control before I use it. I might not understand it, but at least I will have an idea what to look for. :)
You should create Format event like this:
private void comboBox1_Format(object sender, ListControlConvertEventArgs e)
{
e.Value = GetFullIpFormat((string)e.Value);
}
And here is code for formating values:
string GetFullIpFormat(string value)
{
string[] ip = new string[4];
for (int i = 0; i < ip.Length; i++)
{
ip[i] = GetIpPart(i, value);
}
return string.Format("{0:###}.{1:###}.{2:###}.{3:###}", ip[0], ip[1], ip[2], ip[3]);
}
string GetIpPart(int partNumber, string ip)
{
string result = "000";
int iLen = 3;
ip = ip.Replace(".", "");
int iStart = partNumber * iLen;
if (ip.Length > iStart)
{
result = ip.Substring(iStart);
if (result.Length > iLen)
{
result = result.Substring(0, iLen);
}
}
return result;
}
This will do formating for you.
Alternativly you can check input on same event for numbers.
This will do the job for you, happy coding! :)

Retrieve activity name

I'm working in a WPF project and I need one requirement.
This is my main window:
http://img210.imageshack.us/img210/9752/rule.jpg
So, I want that when I drag and drop a custom activity (aggregate Functions), display his name in Compute TextBox... Is there some way to do it????
For example:
1) Drag and drop MaxActivity
2) Display in TextBox Compute: MaxActivity
3) Drag and drop SumActivity
4) Display in TextBox Compute: MaxActivity + SumActivity
5) Drag and Drop MaxActivity
6) Display in TextBox Compute: MaxActivity + SumActivity + MaxActivity1
Thanks a lot!
I would strongly suggest you avoid this design, as however you end up implementing it will introduce brittleness to your code without any benefit (I can already see you are aggregating max and sums, why tell me again?)
If you go ahead, get rid of that "Compute" TextBox. TextBoxes = enter text. You are just rephrasing what is already in the design surface. It makes no sense to allow me to change the text you generate. Use a TextBlock or Label.
Do not, I repeat, not save this in your Activity. This is all UI tasks and should not be saving this information in your Activity configuration
If you have this
public sealed class MyActivity : Activity
{
public string Compute {get;set;} // NO!
and this
<!-- NO! -->
<Label>Compute</Label><TextBox Text="{Binding ModelItem.Compute}"/>
you're probably doing this wrong.
So, how do you do it?
You can parse out your ModelItem and generate this string by listening to changes in the ModelItem and constructing this string every time. Note, your ModelItem will not be set when the constructor is called, so you are going to have to listen to changes to the ActivityDesigner.ModelItem property. There is no event for this, so you will have to know how to listen to changes in a DependencyProperty.
Once you are listening to changes in your ModelItem, whenever a change happens, you can walk down your ModelItem (which is hard) or just get the Activity from the ModelItem and examine it.
var child = ModelItem.Properties["Child"].Value.GetCurrentValue();
if(child == null)
computeTextBox.Text = "Please add some computation stuff.";
else
// hard stuff goes here...
Walking down the path from your Activity's child to whatever activities are held inside can be treacherous, as you can't assume your user has thrown in a Sequence rather than a single MaxActivity, or that they don't have seven nested Sequences, etc etc. So you have to have a pretty complex and brittle set of if else logic to try and parse out what is contained below. And if you start changing properties of the Activity tree outside of the ModelItem you're going to get out of sync with the UI.
Now, after reading that, go back to point 1. I listed in this answer and follow my advice. Drop the idea completely.

C# saving state of the form with all controls

I have a form and I have some buttons doing stuff.
When I press buttons the windows form controls, like textboxes or group-boxes, buttons appear and disappear and change place on my form, for it is a dynamic form :)
However, what I'd like to do is have a button ( BACK ) that will get my form to the state it was before an action of a button, putting back the controls in the place and state they were before action.
I thought of a C class MyState() that will have something like an array of Form1.
I will be saving the form state in that array and when I'll press the back button to get from array that "copy" of the Form state and maybe an index for indexing states.
I have no idea how to implement this, unfortunately. :|
Can anyone show me the right way to do this?
class Mystate
{
private Form1 [] state;
public Mystate(int n)
{
this.state = new Form1[n];
}
public Form1 this[int index]
{
get
{
return state[index];
}
set
{
this.state[index] = value;
}
}
}
Sounds like you want an high level undo/redo feature for your forms.
Here is a framework for such things: http://www.codeproject.com/Articles/10576/An-Undo-Redo-Buffer-Framework
Here is an answer that is close but not exactly the same as your question (The pattern implimented is the same though): How to implement good and efficient undo/redo functionality for a TextBox
MementoPattern: http://www.codeproject.com/Articles/18025/Generic-Memento-Pattern-for-Undo-Redo-in-C
Nothing like this is built-in. You have to do this on your own.
I'd do it like this: First, define precisely what state you want to save. Example:
Control.Bounds
Control.Text
Checkbox.IsChecked
NumericUpDown.Value
...
Now we know exactly what needs to be saved.
Seconds, we need a way to create a snapshot of the current state of the form and recursively for all controls. You can implement this using reflection so that everything will be automatic no matter how many controls you have.
Third, you need to be able to apply a snapshot to an instance of Form. This is the opposite process of (2). This also can be done using reflection.

C# Dynamic Button Event Handler Mechanism

I am creating buttons dynamically for a user-based app. Now I have to tell the new form what text to apply to the buttons via parameters to the form, the form then creates the buttons. Now I have an issue - the events for these buttons: What is the best mechanism to get the button click events through. I cannot access the form from the originating form, and I can only pass simple data types (and arrays).
My first thought is to use a code to reffer to the appropriate method in a static class - basically, pass an array of ints through with the names of the buttons and their onclick handler calls one method - handle(int code) -> where code is used in a giant switch statement to call the appropriate method.
But I doubt this is the best mechanism. I would prefer to create a listener of some sort that simply listens for button clicks, and should the click be unhandled, determine which button was clicked and manage it from there.
I have looked at the observer pattern and I am not entirely convinced this is the best one to follow. The problem is not that there is no solution, the problem is that I want the BEST solution.
This is in C# for monodroid - but the impact of this information should be minimal.
Thanks
Not sure to fully understand what's actually your problem, but here's how you should deal with dynamic controls and event handlers:
Button myNewButton = new Button { Text = "MyCaption" };
myNewButton.Click += (sender, e) =>
{
((Button)sender).Text = "New text here!";
// Another logic could be put here
};
If it was WPF i'd use Commanding but i don't know if it's available for monofroid.
You may look at http://www.codeproject.com/KB/dotnet/EventBroker.aspx
Currently I have two options:
Use reflection - pass a method name to the button and that button can then invoke a method based on the string value passed. Then simply create a static class where all button methods are kept.
Use a switch statement - since I can have delegates that take parameters (one of them being a SENDER object) I can easily send the sender object to a method containing a switch statement which performs an action based on that object.
In my research I have determined that the former (reflection) is preferred, espcially since the number of buttons is rather large.
REFS:
http://embeddedgurus.com/stack-overflow/2010/04/efficient-c-tip-12-be-wary-of-switch-statements/
Large Switch statements: Bad OOP?
Method Factory - case vs. reflection

Categories

Resources