Auto validation of properties in Caliburn.Micro - caliburn.micro

So I'm messing around a bit with Caliburn.Micro, and suddenly I notice something interesting.
I have a ViewModel property called Maximum of type int, auto bound with CM via the naming convention, to a TextBox.
When I enter something that is not and integer, i.e. a character, the textbox' border turns red, and the setter of the property is not called.
Is this an auto-feature of CM?

No, this is the behaviour of WPF. One option is to bind to a string property on your view model, and then perform the validation within the view model (i.e. parse to an int, and provide a default value if the parse fails).

Related

Multiple "default" properties/methods in a VB6 class?

I am trying to make a replacement VB6 class for the Scripting.Dictionary class from SCRRUN.DLL. Scripting.Dictionary has (among other things) a "Keys" method that returns an array of keys, and a read/write "Item" property that returns the item associated with a key. I am confused about this, because both of them seem to be defaults for the class. That is:
For Each X In MyDict
Is equivalent to:
For Each X In MyDict.Keys
Which to me implies that "Keys" is the default operation for the class, but:
MyDict("MyKey") = "MyValue"
MsgBox MyDict("MyKey")
Is equivalent to:
MyDict.Item("MyKey") = "MyValue"
MsgBox MyDict.Item("MyKey")
Which to me implies that "Item" is the default operation for the class.
I've never before created a VB6 class that had a default operation, so upon realizing this, I thought perhaps I could define multiple default operations as long as they all have different signatures, which they do: Keys is nullary, the Item getter takes a Variant, and the Item setter takes two Variants. But this doesn't seem to be allowed: When I use "Tools/Procedure Attributes" to set the Keys function to be the default, and then I use it to set the Item property to be the default, the IDE complains that a default has already been set.
So I think I'm misunderstanding something fundamental here. What is going on in the Scripting.Dictionary object that makes it able to act as if "Keys" is the default in some contexts, but as if "Item" is the default in others? And whatever it is, can I accomplish the same thing in VB6?
OK, answering my own question: I haven't tried this yet, but I gather that "Item" should be made the default, and that I should add an entirely new function called "NewEnum" that looks something like the following (slightly modified from an example in Francesco Balena's "Programming Microsoft Visual Basic 6.0" book):
Public Function NewEnum() As IUnknown
Set NewEnum = m_Keys.[_NewEnum]
End Function
(where "m_Keys" is a Collection containing the keys), and then use Tools/Procedure Attributes to hide NewEnum and to set its ProcID to -4.
What you are observing is the difference between the default member and a collection enumerator. A COM object (including VB6 classes) can have both.
You can identify the default property of a class by looking in the Object Browser for the tiny blue globe or the words "default member of" in the description (see Contents of the Object Browser). The Object Browser will not identify an enumerator method, but if you look at the class's interface definition using OLE View or TypeLib Browser (free but registration required) it's DispId will be 0xfffffffc or -4.
In your own class, you can mark the default property by setting the Procedure ID to "(default)" in the Procedure Attributes dialog (see Making a Property or Method the Default). You already listed the steps for setting up the collection enumerator in your own answer, but you can find this listed as well in the Programmer's Guide topic Creating Your Own Collection Class: The House of Bricks.
Scripting.Dictionary has a dirty secret:
It does not handle enumeration at all, it returns big ugly Variant arrays and your For Each loops iterate over those.
This is one of the reasons why a Dictionary can actually be far less efficient than a standard VB6 Collection.

Flex data binding re-bind when data model not change, possible?

There is a common case that I bind a data model value to a GUI control, say, a TextInput. The data model is retrieve from backend.
If user change the value of the TextInput, then click refresh button to retrieve the data model from backend again, the GUI value will not change back. Re-binding not happen, Since the value of data model not changed, no propertyChanged event fired.
In this case, I must Programmatically set the model value to the GUI after data refreshing done.
I know bi-directional binding can solve this problem(when user change value on GUI, set the new value to data model immediately). But sometimes I cannot use bi-directional binding, for example, the data model is a int, but user input a non-int value, I cannot set the value to data model. So the value in data model do not change, when refresh data, rebinding still not happen.
This will make the data binding useless. How to resolve this?
I put pseudo-code here for now, I will put real code later:
1. retrieve a data model from server, via blazeds or something else.
2. bind the model to a TextInput on GUI.
3. user change the TextInput text.
4. User click a refresh button, triger retrieve the model value again.
5. Now since the model value do not change, no PropertyChanged event fired.
6. GUI value still is the user's input, not the value from the model.
I can clear the model value before set the velue back, make re-binding happen.(but sometimes you do not know how to clean the model value, take int for example, you may do not know the original value and happen set the same value). Or I can manually set the model value to GUI. But both are not good looking.
bi-directional binding not work since if user input a invalid value, I cannot set it to the model. Model value do not change, re-bind will not happen.
Bidirectional binding can be achieved in a variety of ways, not necessarily with the #-symbol. In your particular case you need to use the Binding-tag:
<fx:Binding source="parseInt(someNumberInput.text)"
destination="someModel.someNumberValue"/>
<s:TextInput id="someNumberInput" text="{someModel.someNumberValue}"/>
It's very important not to forget to parseInt() the numeric value.
You can dispatch binding events whenever you want. One way is to simply dispatch a PropertyChangeEvent on all properties you want to update, but another is to add your own binding event in addition to standard binding.
For instance, I think this will work:
[Bindable]
[Bindable (event="allChanged")]//make sure to dispatch this yourself when everything changes
public var myInt:int;
There is a possibility that the custom binding event might prevent Flex from generating the code in the background that does standard binding (I have never done the above, because if I am going to use custom events, I tend to not use the standard binding).
Flash Builder 4.5 has awesome code generation, so you can just convert a public variable to a getter and setter, and it will ask you if you want to fire a custom event for the property. If you check that box, it will write the code for you. Then you add the second metadata tag by hand.
The getter/setter method will perform better, because then each property will have its own event, rather than all of them firing on propertyChange and checking if the property is the correct one. But the other one is less verbose and more maintainable, if it works.
Use a relevant editor to edit a numeric value. Flex can not guess what you want to do.

ASP.NET: Can you use server tags to embed C# or VB.NET expressions into a Javascript function?

I have an enum called SiteTypes that contains several values that are all bound to a dropdown list. On the client side, I need to check this dropdown to see if the selected value is one of those enum values. I don't want to hardcode the value of the enum in the script in case it needs to change, so I want to use a server tag to get it directly from the enum itself. Conecptually, I would like to do this:
function SiteIdChanged() {
var x = "<%=SiteTypes.Employee %>";
}
The way I am doing it now is created a protected property in the codebehind that returns that specific enum value and am doing this:
function SiteIdChanged() {
var x = "<%=EmployeeSiteTypeValue %>";
}
I don't like that, though, because I have to create a special property on every page that I need to do such a check.
Is there a way to do what I want here?
Are you getting a "xxx is inaccessible due to its protection level" error when you compile or run the page? enums are public by default, classes are not. My guess is that you've defined your enum inside your page's class and you aren't explicitly marking it with the 'public' access modifier. Explicitly mark it as public or move it outside of the class and see what happens. If you're planning on using it on lots of pages you should stick the enum definition in in a file in the App_Code folder of your project.
If you don't like your current implementation I would consider using a PageMethod to compare the dropdown selection to the enum value. This approach will probably be cleaner, as you can do most of the logic server-side.
Here's a tutorial on PageMethods:
http://blogs.microsoft.co.il/blogs/gilf/archive/2008/10/04/asp-net-ajax-pagemethods.aspx
As long as your enum is marked public, you can just go with your first option. There's no need to put a property on every single page you want to retrieve the value from.
That approach is really the simplest solution for writing out server side values in your JavaScript.
You can use the Enum.IsDefined Method this well tell you if the selected value from the dropdown is actually part of your enum.
Enum.IsDefined(typeof(MyEnum), myValue)
http://msdn.microsoft.com/en-us/library/system.enum.isdefined.aspx

Default label value for org.eclipse.swt.widgets.Text control; prevent databinding from persisting value

Hy,
suppose a org.eclipse.swt.widgets.Text control connected via databinding to the model Person. The Text represents the surname of the person.
Now, everytime the model is changed, the value is updated, this is ok. Now I want the following:
If there is no value for surname in the model, i want the text-control to contain a hint label, s.a. "Insert surname" which is not supposed to be persisted!
I could create this behavior by adding a modifyListener to the textcontrol which sets the text if the length of setText is 0, I cannot prevent, however, the databinding then to persist "Insert surname"!
I tried extending Text (to override getText), which is not allowed, and wrapping Text into a "LabeledText" requires me to modify the DataBinding!
Anyone aware of a solution for this?
Thx
org.eclipse.swt.widgets.Text.setMessage() is a method exactly performing the requested task.
I think it is quite hard to simulate such behavior with standard SWT widgets. So, probably, you need to create a custom widget, with validation simulation inside. Your validator should return you a validation status, which can be used afterwards.

Can you prevent LinqDataSource from setting a property?

I've got a Linq 2 SQL object I'm trying to update. Two of the properties on this object are related to each other, and setting one sets the other.
So if I do:
Foo.Code = BEER;
The Foo.CodeID property will automatically be set to 5 (or whatever.)
The problem is that LinqDataSource sets Foo.Code, then immediately sets Foo.CodeID... which is not bound to anything since we want the users to set just Code. This immediately sets them both back to null.
I know I can use Parameters to default values, but is there any way to just tell LinqDataSource to not even set a property?
EDIT: Worked around issue by creating a hidden field, and assigning the correct value to that in the formview's ItemUpdating event. Would still like to avoid doing the same lookup four times though...
Would it be an option to make the Code property private (select the Code property in the dbml and set the access property in the Properties window) and create a new public property over which you have more control?
I personally have have written a generator that generates the necessary files for me (like sqlmetal), giving me full control over the code. Perhaps this is an option for you as well, if you do not like the generated dbml.

Resources