How to bind background of a column in silverlight during runtime? - data-binding

I have a grid with bunch of columns in it. To start with this grid is build during run time in the code behind and not much code in XAML except the generic grid, so I can't bind the column background during design time. I have been reading various blogs, questions and found the following as the closest answer.
SolidColorBrush backgroundBrush = new SolidColorBrush();
Binding b = new Binding("BackGroundColor");
b.Converter = new ColorConverterForReadOnly(); //This converter return color based on parameter
b.ConverterParameter = data;
BindingOperations.SetBinding(backgroundBrush, SolidColorBrush.ColorProperty, b);
column.Background = backgroundBrush;
When I ran the code, the binding did not happen, I put a break point (in the first line) inside the converter to see if debug hits the converter at all and it did not hit the converter at all. If I would put
column.Background = new SolidColorBrush(Colors.Blue)
I can see the the column colors set to blue.
What am I missing in the binding that is not letting converter invoked?
Thanks,

The binding is targeting a "BackGroundColor" property. For the binding to be hit, the DataContext of the column control would need to be an object that has a "BackGroundColor" property.

Related

JavaFX TableView multiline tooltip with cell factory and bindings

I have using this code snippet to create tooltips for every tableView cell I propagate via cell factories:
private <T> void addFileTooltipToCells(TableColumn<FileTableBean,T> column) {
Callback<TableColumn<FileTableBean, T>, TableCell<FileTableBean,T>> existingCellFactory = column.getCellFactory();
column.setCellFactory(c -> {
TableCell<FileTableBean, T> cell = existingCellFactory.call(c);
Tooltip tooltip = new Tooltip();
tooltip.textProperty().bind(cell.itemProperty().asString());
tooltip.setShowDuration(Duration.seconds(30));
tooltip.setStyle("-fx-font-size: 12");
cell.setTooltip(tooltip);
return cell;
});
}
Problem is that the tooltips can sometimes have lots of data and should be multilined. From here I found that one should simply wrap the tooltips with and possibly set where necessary. However, the above carefully somewhere copied and trial-error tested code snippet doesn't like the idea. I have tried:
tooltip.textProperty().bind("<html>"+cell.itemProperty().asString()+"</html>");
tooltip.setText("<html>"+cell.itemProperty().asString()+"</html>");
First says in IDE: Incompatible String cannot be converted to ObservableValue
Second one generater following tooltips: " String binding [invalid] " :)
And before somebody starts with the usual "the error message says it all, read it" stuff, I know that there are probably a simple answer for this, but having these lambdas combined with the binding concept and cellfactories, I just have to give up and try to get some guidance from here.
Answer to those who face the same problem. You can use the "normal" binding but just apply the tooltip preferences to every tooltip the cellfactory creates simply by defining:
tooltip.setMaxWidth(750);
tooltip.setWrapText(true);
Setting preferable width will create tooltips with lots of extra blanks if the data is shorter than the width. Max width works like a charm. Next step is probably to make width parameter dynamic so that it calculates the max width based on stage resolution.

How to replace one mxml instance with another?

I am pretty new to Flex.
What I am trying to achieve is to have two different layouts and initialize them based on the user's choice. Each of these layouts is defined in its own mxml component.
I have two components:
and
I could add both in the beginning and have only one visible but I don't want to go down that road. What I tried so far is to have an event handler that replaces the current instance but I hit a wall. Let's say that LeftAligned is the component initialized first and then I want to change it with RightAligned. Now:
If I try to replace the lement based on its id: newElement:RightAligned = new RightAligned(); LayoutArea = newElement; I get a implicit coercion error that it can't convert RightAligned to LeftAligned.
If I try to removeElement(LayoutArea); addElement(newElement); then I get an exception thrown from other parts of the application that call LayoutArea's methods (event based).
What solutions are there for this? Thank you

Two-way data binding in actionscript causes stack overflow

I'm binding two AutoCompleteModified objects to one another; meaning you type
in one and it selects the correct object in the other. It works fine when I
define it in MXML:
However, a user can add a new row to a Grid and then I set up the binding and
objects via actionscript and it gives an 'undefined' error: ChangeWatcher line 427/wrapHandler.
var innerHBox:HBox = new HBox();
var dtc_acm:AutoCompleteModified = new AutoCompleteModified();
dtc_acm.dataProvider = data2;
dtc_acm.labelField = 'id';
var cp_acm:AutoCompleteModified = new AutoCompleteModified();
cp_acm.dataProvider = data2;
cp_acm.labelField = 'name';cp_acm.width = this.CP1.width;
BindingUtils.bindProperty( dtc_acm,'selectedIndex',cp_acm,'selectedIndex' );
BindingUtils.bindProperty( cp_acm,'selectedItem',dtc_acm,'selectedItem' );
innerHBox.addChild( dtc_acm );
innerHBox.addChild( cp_acm );
I don't understand what may be happening here. Can anyone see any potential
problems in my code? If I only keep it 1-way binding then it works fine. But both throw this error. Is there something about not only doing it 2-way in actionscript, but adding components that aren't on the stage yet?
Thank you kindly for any helpful tips,
Matt
I'm trying to do the same thing. It works in MXML but not in AS. For example, this works:
<mx:TextArea id="t1" verticalScrollPosition="{t2.verticalScrollPosition}" height="200"/>
<mx:TextArea id="t2" verticalScrollPosition="{t1.verticalScrollPosition}" height="200"/>
If I scroll one of the TextAreas then the other one scrolls too. However, trying to do the same thing in actionscript causes a stack overflow (infinite loop)
BindingUtils.bindProperty( _t1, 'verticalScrollPosition', _t2, 'verticalScrollPosition' );
BindingUtils.bindProperty( _t2, 'verticalScrollPosition', _t1, 'verticalScrollPosition' );
I used the -keep-generated-actionscript compiler option and looked at the generated asctionscript for the mxml example and it creates a couple mx.binding.Binding objects and it looks like the key is setting the twoWayCounterpart property. I haven't tried mimicking that code yet but it might help you.
Since the two components are bound to each other like this I'm not surprised you are seeing this, I'm more surprised that it worked via mxml.
Have you tried changing the (optional) 5th parameter in bindProperty to true? That parameter is commitOnly and defaults to false. That may fix your problem.
Another approach could be to have an intermediary variable to store the selected item and bind your components to that variable.
Hope that helps.

FLEX: how can I get the width of my linkButton object?

How can I get the width of my LinkButton object ?
myLinkButton = new LinkButton();
myLinkButton.label = "blabla";
myLinkButton.setStyle("fontSize", 24);
myContainer.addChild(myLinkButton);
trace (myContainer.width); //this doesn't work because I haven't directly set the attribute
thanks
First, what does that trace() show? Is it null or undefined or NaN or simply a wrong value?
Then, there are several ways I can think of how you could get around this problem:
Try using getBounds() or getRect(). These methods return a Rectangle object working as the DisplayObject's bounding box (including all coordinates and dimensions). Sometimes Flex behaves a bit weird and returns wrong/off results for the coordinates or dimensions of objects.
Try experimenting with validateSize() and/or measuredWidth. Perhaps you're trying to access the width property too soon so that Flex cannot do the measuring/layouting in time.
Similar idea: what happens if you use myContainer.callLater(trace, [myContainer.width]); (assuming your myContainer inherits from UIComponent)? If you do get a valid result using callLater() but not when accessing width directly then Flex just hasn't had a chance to layout and update the container.
You could also try using this method, which creates a Bitmap from the object and returns the Bitmap's height/width. This is especially useful if you have components with visible = false in your container, because Flex doesn't handle invisible components well in that regard.
Finally, you could try accessing $width in the mx_internal namespace and check that property's value. However, using mx_internal is sort of a very ugly hack because these properties and methods weren't meant for external use and are subject to change any time (so your component could stop working when a new version is released) - so use with caution.

'Pre-measuring' Flex Components

I'm implementing a custom Flex component that provides a scrollable viewpoint onto a (possibly very large) data grid. I'm using the ItemRenderer pattern, such that I only have UIComponents for the elements visible on the screen at a given time. In other words, something similar to the standard DataGrid control.
One requirement I have is to dynamically size the grid cells to fit the provided data, such that the column widths and row heights are known up front. (The column widths and row heights can't fluctuate as the user scrolls and new cells come into view.)
This requirement implies a 'pre-measure' phase of the entire grid to be performed when the component's dataSource or itemRenderer is changed. I'd like to use the standard Flex component measuring operations to perform this pre-measurement phase.
My current strategy for this pre-measure phase is to:
Obtain an itemRenderer instance
Initialize the itemRenderer
For each cell in the data source:
Set the itemRenderer's 'data' object to that cell's data
'commitProperties()' on the component
'measure()' the component
Update column width/row height appropriately based on measurement results
I'd rather not attach the itemRenderer to the application's display list, but that means it won't be initialized by the framework. Also, I need the renderer's initialization and commitProperties/measurement phases to occur synchronously. I'm scared of how much of the Flex component lifecycle management framework I'll have to replicate to accomplish this.
So I call on those more experienced than I for words of wisdom:
Any thoughts on the feasibility of this strategy?
Any suggestions on how I could elegantly make use of the framework to perform this measurement for me?
Any better strategies to determine cell size?
I studied the framework code a bit, and if initial results are an indication, this isn't as painful as I feared. The guts of it:
var renderer:IListItemRenderer = getRenderer();
renderer.initialize();
for each (var cell:Object in cells) {
renderer.data = cell;
renderer.validateProperties();
renderer.validateSize(true);
// Access renderer's size properties here
}
Passing the 'recursive = true' flag to validateSize is the key that I was missing previously. Unfortunately there's no equivalent flag for validateProperties, so I'll probably have to implement that myself to make it reliable for arbitrary ItemRenderers.
I've never applied itemRenderers this way, so, not sure how much this would come into play with you're approach, but are you setting
super.data = data
at the top of your renderer's data setter? i.e:
override public function set data(value:Object):void
{
super.data = value;
...
}
If not, you might try adding that and see if it removes the need for a recursive flag in validateProperties().

Resources