JavaFX 8 multiple bi-directional bindings - binding

My borderpane on the right contains a TextField. The center contains a draggable StackPane. I'm trying to bind the layoutX of the stackpane with the textfield. However, since I'm using MVP, there is a model (controller) in-between.
The text field (called 'idTopX' which comes from an FXML layout) has this binding to the model
idTopX.textProperty().bindBidirectional(model.topXProperty);
where model.topXProperty is defined as:
public StringProperty topXProperty = new SimpleStringProperty();
In turn the model binds its topXProperty to the draggable pane:
StringConverter<Number> converter = new NumberStringConverter();
Bindings.bindBidirectional(topXProperty, dragPane.xProperty, converter);
and finally the draggable pane has:
public DoubleProperty xProperty = new SimpleDoubleProperty();
with the appropriate getters and setters for the property linked to the pane's layoutX.
So I have this big chain of bi-directional bindings TextField <-> model <--> draggable Pane <--> pane.layoutXProperty
It works while dragging the pane around, but as soon as the textfield is altered I get:
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: Bidirectional binding failed, setting to the previous value
Nothing in the stack trace points me back to my source and with the 'cryptic' message 'binding failed', I'm clutching at straws. Any suggestions? I'm also open to better implementations, because I suspect that my approach may also not be correct.

Related

How to disable JSF components programmatically

We have a JSF application with <rich:tab> which shows fields depending of some configuration stored in a database, so the components are not defined in the .xhtml page but have to be generated programmatically such in this example:
Components are generated in a panel:
<rich:tab id="someTab" header="#{msg['someHeader']}" immediate="true">
<rich:messages/>
<h:panelGrid id="generatedComponentsContainer"/>
</rich:tab>
Component generation example (simplified for simplicity):
FacesContext ctx = FacesContext.getCurrentInstance();
UIPanel panel = (UIPanel) ctx.getViewRoot().findComponent("someForm:generatedComponentsContainer");
text = (UIInput) ctx.getApplication().createComponent(ctx, "javax.faces.Input", "javax.faces.component.UIInput");
text.getAttributes().put("label", someLabel);
panel.getChildren().add(text);
Those components have to be shown disabled depending on some condition, so I used the following code to disable each of them if needed:
if (!showEnabled) { text.getAttributes().put("disabled", "true"); }
This method works for UIInput and HtmlInputTextarea but it is not working for UICalendar, throwing a IllegalArgumentException (argument type mismatch).
How can I disable the calendar?
I have been also wondering if this code just disables the component at the client side leaving it enabled at the server. This would probably be a security threat as somebody could enable a component via Javascript and submit the form to the server. I am not sure about this being possible, please advise if I am wrong.
After further research I noticed there are some classes that extend the ones we were using in our project. Those classes have a getter/setter for the disabled attribute which also disables the component in the server side. I tested this disabling the components programmatically and removing the disabled attribute while browsing the page to allow edition and submit. When submitting the form, the values are setted in the request but ignored at the server side. Bean values remain unaltered.
The classes we have used:
HtmlInputTextarea instead of UIInput
HtmlInputText instead of UIInput
We were already using UICalendar, which fits the purpose
A sample of code:
HtmlInputText text = (HtmlInputText) ctx.getApplication().createComponent(
ctx, HtmlInputText.COMPONENT_TYPE, "javax.faces.component.html.HtmlInputText");
if (!showEnabled) { text.setDisabled(true); }
When debugging the contents of the HtmlInputText you can see a ComponentStateHelper object (named stateHelper) which stores the disabled state of the component (among other data). Its superinterface is StateHolder:
public interface StateHolder
This interface is implemented by classes that need to save their state
between requests.
I understand that server-side state of the component is stored in this object, but I am not sure whether it is stored only here or in more points, or even if my interpretation of its purpose is correct. Feedback from an expert would be very useful.

Custom ToggleButton in Xamarin.Android

I am working on a MvvmCross based android app. The app contains (among other things) a large number of ToggleButton(s). The buttons are added in .axml files. Their Checked property and Click event are bound to view-model properties. Since the Checked property of the each ToggleButton should reflect the state of some property on a application server, I don't want their checked state to be changed when the user clicks them, but only when the bound property on the view-model is changed. An example how this "special" toggle button should work: When the user clicks it, the "Checked" property of the button does not change only the ICommand to which the click event is bound to is invoked. The method invoked by the command in turn changes the value of the property on the view-model(if executed successfully). Extending a ToggleButton in WPF or Windows Forms to described functionality is easy but I don't know how to do that in android. Any ideas will appreciated.
Uroš
I found the solution to my problem. It seems it had to do something with the way I set up the bindings for my ToggleButton
MyToggleButton was implemented as:
public sealed class MyToggleButton : ToggleButton, View.IOnClickListener
{
public MyToggleButton(Context context, IAttributeSet attrs)
: base(context, attrs)
{
SetOnClickListener(this);
}
public void OnClick(View v)
{
Checked = !Checked;
}
}
As you can see I just set the Checked property back to previous value when ever the user clicks the button. In the asmx I use the following block to add the button.
<controls.MyToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
local:MvxBind="Checked Value;Click ClickCommand" />
As it turns out the problem with described solution is that the OnClick(View v) method is not executed when the user clicks the button as long as the .axms file contains binding to Click event. I have no idea why that is so I would love any explanation. The workaround I used is to define custom event in the derived class, raise the custom event in the OnClick event handler and than bind to that event.
Uros

Textbox inside a Repeater inside a Custom Server Control loses values

I am developing my first Custom Server Control which will display a list of fields, with textboxes. When the page containing this custom server control is posted back, the values inside the textbox are lost as the repeater is either re-binded, or the viewstate isn't holding onto the values.
How can I get the repeater to hold the values of the textboxes between postbacks?
Cheers!
Most likely you are not re-creating your Custom Control at the right stage of the page lifecycle. Viewstate is restored right after the OnInit() event of the lifecycle. So if you are adding the control after this, the control is not there for the Viewstate to be restored.
Try moving the creation of your dynamic control to the OnInit() event of the page.
If you dynamically populate your repeater? then you might have a timing creation issue based on when View state is loaded.
Try putting all your dynamic control creation into the Page_Init event to preven the timing creation issue.
ie instead of using the Page_Load event use Page_Init event to bind data dinamically in your control.
protected void Page_Init(object sender, EventArgs e){ ..... }
regards, I hope I have been helpful

Cannot add constraint to DataTable which is a child table in two nested relations

void ReadXMLData()
{
string filePath = #"D:\XMLFiles\cms.xml";
DataSet ds = new DataSet();
ds.EnforceConstraints = false;
ds.ReadXml(filePath);
}
When I read the above xml file I got the error: Cannot add constraint to DataTable which is a child table in two nested relations.
Kindly help me that how can I overcome the mentioned DataSet exception?
Thanks in advance.
do you have any control over the XML formatting? I believe XML where child nodes have the same names as ancestor nodes are not fully supported. Would that be your case?
Edit: this might be helpfull: http://www.codeproject.com/KB/cpp/dataset.aspx. (MC++, but the same principles appy).
xml data is loaded into VS.NET 2005 xml editor
right clicking "view data grid" yields
"Cannot add constraint to datatable 'xxx' which is a child table in two nested relations"
HOWEVER if you move element before and , or if you delete or
right clicking "view data grid" properly displays the data grid. Note that and are indentical.

Using Mode=TwoWay and AutogenerateColumns=True in Silverlight 3 DataGrid

My List<BusinessObject> has some public properties that I want to bind to columns in a DataGrid. Unfortunately, the names of the public properties are not good and I may not even know what they are until runtime. For this reason, I set AutoGenerateColumns=True and interecept each DataGridAutoGeneratingColumnEvent so I can inspect what it is and either cancel it, hide it, or name the header something else.
It works great but I cannot figure out how to set the Mode=TwoWay so that my INotifyPropertyChanged events get fired once all the columns are generated and somebody edits a cell.
Bonus question:
On navigating up and down the rows of the grid, does the grid's datacontext automatically get set with that row's BusinessObject?
Thanks to this post, I learned that the binding happens on DataGridTextColumn. So the way to set the Mode at runtime is:
1 private void DataGrid1_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
2 {
3 DataGridTextColumn tc = (DataGridTextColumn)e.Column;
4 tc.Header = "Custom Header";
5 tc.Binding.Mode = BindingMode.TwoWay;
6 }
Now that I have TwoWay binding, I have to figure out how changes make it back to my BusinessObject.
If the binding is correct your business objects will automatically receive the required updates. To do you binding programmatically you might need a little more code, something like:
...
Binding binding = new Binding("Propertyname");
tc.binding.Mode = BindingMode.TwoWay;
...

Resources