JavaFX how to assign content to a child node UI controller - javafx

I have written the following code, where I assigned the MasterNode as a new treeView.
MasterDetailPane pane = new MasterDetailPane();
pane.setMasterNode(new TreeView());
pane.setDetailNode(new PropertySheet());
pane.setDetailSide(Side.BOTTOM);
pane.setShowDetailNode(true);
Now I want to populate and manipulate that TreeView programmatically. I think I need to do a pane.getMasterNode()..., but some how I should be able to access that controller and say something like,
pane.getMasterNode().setRoot(rootNode);
But I can't figure out how to get a hold of the controller, and get it cast as the right type of object in order to assign the rootNode. How to do I access that buried controller to assign a rootNode?

Okay, so I did figure it out. I'm just getting started in javafx, so bear with me. Simply casting the node to a tree view was all that was required to get the UI class back and make it accessible.
TreeView myTree = (TreeView) pane.getMasterNode();
myTree.setRoot(rootNode);
And it works as expected.

Related

JavaFX binding in initialize method

I am trying to create a binding to provide a button a way to disable/enable itself whenever a listview contains items or not. However, I don't get it to work.
This is my initialize method
private void initialize(){
runButton.disableProperty().bind(Bindings.isEmpty(listView.getItems());
}
Adding items to the listView has no effects whatsoever on the disabled/enabled state of the button.
If I put the above line of code in another random function that is called later on in the program, it works.
I've read that the bindings might be garbage collected so I've also tried to create a field of the binding to then apply to the disabledProperty. This does not work either.
Any ideas?
EDIT:
listView.setItems(observableFiles)
is used to populate the list
Do you call listView.setItems() anywhere in the code? If so that will explain why it doesn't work when you put it in initialize because you're binding to the old list object whereas the ListView is using the new list object.
Edit: Just seen your edit, it seems you really did this. Try calling the bindings after you call setItems.
As another alternative you could add listener to ListView itemsProperty and if the changed list is empty trigger disable on your runButton.

Simple binding with JavaFX8

I have been exploring JavaFX8 for a few days and am trying to educate myself with the concept of binding. I've created an ObservableList like this
private static ObservableList<XYChart.Series<String, Number>> chartData = FXCollections.<XYChart.Series<String, Number>>observableArrayList();
I then go through a few steps to create an AreaChart and have had success calling the setAll() method below
areachart.getData().setAll(chartData);
It is my understanding though that bindings would allow me to remove this step by associating the data property with the list. If the list changes, the chart data property would automatically be "updated".
I've tried to bind the data property like this
areachart.dataProperty().bind(chartData);
However, its asking for a syntax that I'm not familiar with at all
(ObservableValue<? extends ObservableList<Series<String, Number>>> arg0)
Can someone please help me create the correct syntax to bind the list to the area chart? If I've gotten the concept of binding all mixed up please let me know.
JavaFX's ObservableList is special List which can be observed for its children manipulations by attaching an event handler to it. Please read related javadocs for more info.
In JavaFX, the ancestor of all charts, XYChart has a dataProperty() which is ObjectProperty<ObservableList<XYChart.Series<X,Y>>>. Namely this is a property field that holds an object whose type is ObservableList. And this is the field you need to set its holding observable list directly as
areachart.setData(chartData);
Now the data of areachart and chartData are referencing the same list, any removing/adding to chartData will be "reflected" to areachart's data and vice versa.
The
areachart.getData().setAll(chartData);
is also valid but it will copy list-to-list. I.e. it will internally loop the chartData and copy its children (XYChart.Series in this case) into the data observable list of areachart. Resulting to different lists, so no relation, no "reflection" between them.
The
areachart.dataProperty().bind(chartData);
is wrong. Because it is trying to bind, roughly saying, the property<list> to list.
Even though the dataProperty is ObjectProperty<ObservableList<XYChart.Series<X,Y>>>, binding to it through dataProperty().bind() will expect ObservableValue<? extends ObservableList<Series<String, Number>>>, where ObservableValue is a superclass of ObjectProperty. This is by design, there were discussions on this topic on SO, but cannot remember the actual Q&A entry. Try to search them.
Before going deeper in JavaFX refer to Using JavaFX Properties and Binding and other resources to understand it better. Generally speaking property is a wrapper to its holding object, by providing an observer like pattern to its state changes and also providing flexibility to plug up to other property objects through JavaFX APIs. See for example Bindings and its usage examples on the net.

How to add database views as part of IDatabaseInitializer

I would like to map a POCO class to a database view. My goal is to create the view using a custom database Initializer (Implementing IDatabaseInitializer<T>)
Unless I'm mistaken, I must decorate the class that maps to the view with the [Table("MyViewName"] attribute. However when I do this Database.CreateIfNotExists() will create a table called MyViewName, before I get a chance to execute the SqlQuery command that creates the view.
I suspect I'm doing something out of order, but with only one method in the IDatabaseInitializer interface to work with, I can't see what it could be.
One possible solution is to simply let the CreateIfNotExists do it's thing, and then drop the newly created table and replace it with a view. Seems somewhat hackish but it does work.
if (context.Database.CreateIfNotExists())
{
context.Database.ExecuteSqlCommand(#"drop table MyCustomView");
context.Database.ExecuteSqlCommand(#"create view MyCustom View as ...");
}

How to return two types of objects in an ASP.net MVC view

I have say class/ojbect one which I am returning as details. But then there is a second class that is related to the first that I want to list (and have an option to look at the details). How do I get return both of those?
Example is like in an item as the main piece but there may be details or other items that are related to the main item. I will select them with a linq query but then how do I return them to the same view?
Do I need to have some sort of partial or other form to display the second object type?
I don't see where returning the view I can return both.
My thought for right now is to create a new class that contains both of the object types but I know there has to be a better way.
My thought for right now is to create a new class that contains both of the object types but I know there has to be a better way.
That is the right way. Create a ViewModel class that contains all the data that view needs and pass it to view.
You can either pass it to View through ViewState or ViewBag (depending on which MVC version you are using).
for the first object "main object" return it as the model of this view and for the details
put them into ViewState and cast them back within the view

Populate comboboxes INSIDE a datagrid with UNIQUE data IN actionscript (flex)

i've searched for several hours, and didn't find an answer for my problem.
i'm trying to place comboboxes in a datagrid filled with DYNAMIC data. (the number and the content of these comboboxes always change. i don't know in advance how many columns there are, where i need to use comboboxes. so every single combobox gets a unique dataprovider, which comes from an external source, WHEN the program runs.)
-i found MANY threads discussing this problem, but solving via crappy mxml files, filling the comboboxes inside the sourcecode by hand. i want to point out, that isn't good for me.
-i found a better solution, in which they used some sort of custom itemrenderer to get the data from the internet. (kind of a country chooser thing) but sadly that wasn't good enough, because the number and name of the countries in the world are static more or less, they don't change. so their renderer class didn't depend on any parameters from the main algorithm.
but in my program i calculate the data in my own actionscript objects, then fill an arraylist with that. so at the beginning i load the desired data from the net, and when i get the response of the urlrequest, AFTER that i start to populate the datagrid/combobox.
i can fill any datagrid or combobox without trouble, but to put that combobox inside a datagrid cell seems to be impossible.
could anyone please help? it drives me crazy. i managed to do this in several languages before, c#, java, even php+html, but in flex it looks way too complicated then it should be.
EDIT:
i'm aware, that this amount of network activity could mean some load on the server. i didn't design the philosophy behind it, i just need to wrote a client which meets the expectations. my program looks something like this:
(i'm willing to rewrite any part of it, just to make those nasty comboboxes work)
=========
main.mxml file
this is the main program, i handle some login related stuff here, and set basic design properties for the datagrids. (for example: maxwidth, maxheight, layout constraints etc.)
nothing interesting, except the command when i instantiate the actionscript class, which i wrote to fill the datagrid.
"..<fx:Script>
<![CDATA[
private var myGrid1:MyGridType;
..
somefunction {
myGrid1 = new MyGridType(theDatagridDefinedBefore, "argumentNeededToFillDataGridsWithUniqueData");
}
]]>
</fx:Script>.."
=========
MyGridType.as file
in the constructor i call a urlrequest with the help of the second argument, then add an eventlistener to it. when the data arrives, the eventlistener fires the filler function: i read the results into an arraycollection, then make it the dataprovider for the the datagrid in the first argument.
so far so good.
here comes the trouble with the comboboxes. for a specific number columns, i instantiate my combobox class. let's call that class "MyComboBoxType".
"..
blablabla = new MyComboBoxType(theDatagridDefinedBefore, param1, param2, param3);"
=========
MyComboBoxType.as file
i do nearly exactly the same, what i did in the MyGridType class. call for help from the net with param1-2-3. when i receive the data, fill an arraycollection. maybe set that arraycollection to be the dataprovider for a combobox. AAAAAAAND now i want that arraycollection or combobox to be on the datagrid "theDatagridDefinedBefore".
I know it's not exactly what you're trying to accomplish, but I had a somewhat similar issue in the past. Take a look at How to get the value of a ComboBox within a DataGrid to see if it helps.
If it were me, I would populate the entire ArrayCollection set before binding them to the datagrid if at all possible.
You should build up your custom [Bindable] data structure - say MyGridData class - for the rows in the grid (if you haven't done it yet);
the dataProvider of your grid should
be an Array / ArrayCollection /..
of MyGridData objects.
this step clearly works already, but
for the integrity: override the
getItemEditor function, or specify
it explicitly using mxml, to return
the combobox when needed.
as for the dataProvider of the
combobox, you should specify the
data.comboArray from inside the
renderer class, where data is the
MyGridData instance used by the row
you are processing. (overriding the
set data(value: Object):void
function, you can pre-process it.)
this way, you are working with the
reference of your original instances,
and by the binding you can detect /
show any changes to them directly.

Resources