I am building a Xamarin Forms Application and using XAML that is databound to a ViewModel that contains the model that is stored in Realm datastore.
When Two Way databinding it turned on the view will throw the error
Cannot set values outside transaction
Which includes
InnerException {Realms.RealmOutsideTransactionException: Cannot set
values outside transaction at
Realms.RealmObje…} Realms.RealmOutsideTransactionException
I'm not sure why the data binding is wanting to set the value back on the RealmObject when its loading the View that shows the Entry object that its databound to.
By Default the Mode=TwoWay. I have to change it to Mode=OneWay to get the view to load the databound data.
Is this a bug?
According to this article, this should work.
https://blog.xamarin.com/cross-platform-development-with-xamarin-forms-and-realm/
When you have two-way binding then the Realm needs to have an active Transaction as shown in the QuickJournal sample's JournalEntryDetailsPage.
I'm not sure why the data binding is wanting to set the value back on
the RealmObject when its loading the View that shows the Entry object
that its databound to.
This puzzles me too. It is a quirk of the way Xamarin Forms implement two-way bindings. If a string property is blank, then it doesn't trigger the setter. However, if there is a value in the RealmObject's property, it seems to fire a Xamarin.Forms.Platform.IOS.EntryRender:OnEditingChanged and attempt to set the same value back again. I consider this a bug in Xamarin Forms. It should not be propagating the unchanged value back as far as the viewmodel.
Related
I am using asp.net MVC3 and I am very new to this technology.
My models are designed in such a way that the properties will throw validation errors if the data is invalid. In this case, the properties are not set with invalid data.
When I redisplay my editing-view, validation error messages are shown; however the values that the user previously entered are gone because the model that it is bound to only contains the old-valid data.
For example, say I had a Person class and the Name property cannot be a null or empty string otherwise it throws a validation exception and prevents the property from being set. Now say the user removes the value from the Name property and tries to save the Person from the web. A validation exception will be thrown and handled properly to add the error to the ModelState so that it is displayed on the screen; however the old value for the Name is redisplayed since the invalid, empty string never made it into the property.
I do not know how to solve this problem and any advice on the issue would be greatly appreciated.
My advise is allow invalid data but use validation attributes. You wont save invalid entities so there is no problem and this is the standard approach these days. If you don't want do that, there is no easy solution. Most simple solution would be using the info from Request.Form
You should implement IValidatableObject to performe this kind of validation at server side.
From MSDN IValidatableObject Interface:
Provides a way for an object to be invalidated.
Theres an exemple here Using IValidatableObject Custom Validation, also from MSDN.
The solution to this problem was to create a ViewModel that allowed invalid data to be entered into this. This solution also simplified my ModelBinder classes because it took on most of the work.
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.
Environment: VS2010, SL4, RIA Services
I have an SL4 UI that I developed against data objects that were instantiated from an XML file (so that I didn't have to worry about the back end of the app while I worked on the front end). In this UI, I have a data grid that shows properties for each object in the collection of data. I also have a details panel that shows editable details for the object that is selected in the datagrid.
In this version that uses the "mocked" data, I have the binding for the editable properties set as TwoWay. When I edit a value in the details panel, the corresponding value in the data grid is updated. (I don't allow editing directly in the grid.) I can move to another record, then return to record I changed and I can see that the value has successfully been changed (on the client side, at least).
I then added RIA Services to the mix so that I am now retrieving the data from the back end. The data loads fine, but when I try to modify the value of a property in the details panel, it doesn't "stick". That is, the value in the data grid doesn't update to reflect the new value and if I move to another record and return to the changed record, the old value is shown.
Since RIA Services is the thing that changed, I'm assuming that that's where the problem lies.
Next step... I placed a break point in the code generated by RIA Services for client-side consumption inside the setter for the value that I'm changing. When the data is first loaded, the code in the generated setter works fine. When I make a change to the property, however, there appears to be a problem.
Here is the generated code in the setter:
set
{
if ((this._quantity != value))
{
this.OnQuantityChanging(value);
this.RaiseDataMemberChanging("Quantity");
this.ValidateProperty("Quantity", value);
this._quantity = value;
this.RaiseDataMemberChanged("Quantity");
this.OnQuantityChanged();
}
}
After changing the data, I step through the above code in the debugger. When I execute the "RaiseDataMemberChanging..." line, the setter is exited and the rest of the statements are not executed. No exception appears to be thrown and the app continues, but the value isn't updated because the line of code in the setter that sets actually sets the value doesn't appear to be executed.
Any ideas on what the problem is (or at least what I should try next)??
Here is some additional information that may be helpful:
The editing happens in a text box in the details panel. Here's the Xaml for the text box:
<TextBox Grid.Row="2" Grid.Column="0" Text="{Binding Quantity, Mode=TwoWay}" />
Here's the binding used in the data grid. (I don't allow editing there. I set IsReadOnly="True" for the data grid.):
<data:DataGridTextColumn Binding="{Binding Quantity}" Header="Quantity" />
These are both unchanged from when I was binding to the mocked data. The code-behind had to change in order to bind to the different data source. Here's the binding code from the mocked data version:
InitializeComponent();
_industrialDetailsView = new PagedCollectionView((IEnumerable)IndustrialDetailsData.DataSource);
grid.ItemsSource = _industrialDetailsView;
And here's the binding code that uses RIA Services. Note that there is an IndustrialDetailsService on the server side from which the IndustrialDetailsContext is generated by RIA Services.
_industrialDetailsContext = new IndustrialDetailsContext();
_industrialDetailsContext.Load<IndustrialDetailDto>(_industrialDetailsContext.GetByFacilityAndAssessmentYearQuery(202, 2009),
loadOperation =>
{
_industrialDetailsView = new PagedCollectionView(loadOperation.Entities);
grid.ItemsSource = _industrialDetailsView;
}, null);The data context for the details panel has not changed. It is set from the data grid's SelectionChanged event handler like so:
IndustrialDetailDto industrialDetails = (IndustrialDetailDto)grid.SelectedItem;
DetailsView.DataContext = industrialDetails;
Please let me know if there is other information that would be helpful.
I finally determined the nature of the problem when I made the datagrid editable and tried changing the value directly in the datagrid. When I did that, I got an error message saying:
"This EntitySet of type 'X' does not support the 'Edit' operation."
I was then able to solve the problem by adding placeholder methods to the domain service for "Delete", "Insert" and "Update" so that the generated EntitySet allows editing.
Nevertheless, I still think this is a problem that needs to be addressed by Microsoft... I should have received an error message when I tried to modify the text box instead of the generated code simply exiting the setter prematurely.
I have read that viewstate is not there in asp.net MVC application.
I am doing model validation. Now if i have two text boxes on my page,and i am doing required filed validation for both of them in model. This validation is done on server side on click of a button. I will fill one text box and click on submit button. It does the validation and returns the result saying second field is required. At this time value of the first text box is retained. So can you tell me how this text box is retaining the value even after postback?
There is no "postback". There's just a post.
Server returns HTML.
Browser renders it.
User POSTs crap data.
All of the user's submitted data is saved in the Controller.ModelState collection.
Each ModelState entry has its Errors property set if there is a validation error.
Server looks at crap data. Returns page same as (1) except that it includes user's submitted data, good or bad, and validation errors for the crap data.
Browser renders that.
When you call, say, Html.TextBox("someName", someValue) then the text box will contain someValue unless there's a ModelState key for "someName", in which case the value from ModelState is used instead. This is how the default data (if any) is displayed originally, but the user's data is displayed after an error.
Read about ModelState. When you post http form, values are stored in ModelState object and reused when you generate form again using html helpers (Html.Label, Html.Hidden, Html.TextBox).
Form is shown using Html.TextBox().
User enters value first time.
Form is posted.
ModelState object holds textbox value.
Form is shown second time using Html.TextBox() again. Method looks into ModelState and sets its value again as it was posted first time. Even if you provide new value, it will be searched in ModelState object.
View is rendered using Model. On failed validation if you pass the same model (with ModelState errors) to the view it will repopulate the same view with extra Validation messages which are rendered using ModelState Errors.
The value of the textbox is bound to the Model value.
Upon validation failure the page is redisplayed with it's Model in the state it was when the submitted (i.e. with a value for the first textbox) and any ModelState Errors added.
No viewstate coming in to play ;-)
Enabling view state is actually supposed to retain values of the controls if you are posting back to the same page
Enterprise Library Validation Application Block (VAB) integrates with ASP.NET and also with WCF.
Is there a way to integrate ValidationResults created in WCF with ASP.NET?
e.g. an ASP.NET web page invokes a WCF service. The WCF service validates the data using VAB and returns validation information via a FaultContract. The ASP.NET page can take the results and display some error messages. However, a common approach is to indicate which fields have errors (e.g. inline message or asterisk). It seems that most of these approaches will involve being able to correlate the validation result with a control or with a validator.
I don't think there is an out of the box solution but was also curious if anyone had done this and what their approach was.
Since there is no out of the box solution and there aren't any answers posted, I will share what I implemented. I'm not in love with the approach but it is working for me.
Overview
The basic approach is for the ASP.NET page to populate a mapping between properties on the DataContract objects to the ClientId of the control that is being validated. When a validation error occurs the ClientId is returned back from the service to the asp.net page as part of a FaultContract. Then the details from the FaultException are extracted; the ASP.NET page retrieves the ClientId of the control that caused the error and appropriate action can be taken (e.g. change control look and feel or set the text on a validator).
Details
All of the DataContract objects inherit from a base class that exposes a Dictionary. This dictionary is used to map object properties to ASP.NET controls. In the Dictionary, the key is the property name on the DataContract object and the value is the ClientId of the control. Before invoking a service, the client must attach the Dictionary to the DataContract object.
When a ValidationResult is created by Enterprise Library it contains a property called Target which is the object that was validated. ValidationResult also contains a property called key which is the name of the property from the target object that was validated. The ValidationResult key is also a key into the Dictionary that was set in the ASP.NET page before calling the service.
With the ValidationResult key, the ASP.NET supplied information (ClientId) can be extracted from the ValidationResult Target. The information is then added as the Tag of the ValidationResult. Unfortunately, Tag is a readonly property so it has to be set by creating a new ValidationResult and passing the tag to the constructor.
The collection of ValidationResults is then transformed to a pre-existing CustomValidationResults collection (which looks just like ValidationResult) that we needed to use. The CustomValidationResults are then added to a custom ValidationFault and a FaultException is thrown.
The ValidationFaults are then extracted from the FaultException in the ASP.NET page. The ValidationFault contains the ClientId of the control which is associated with the error so the page can choose to display the Messages as it sees fit.