I have some custom ViewCell elements and most of them show and hide some components according to some properties of the BindingContext. I need to check values of some properties and show and hide some elements in the ViewCell, and also adjust the cell height accordingly.
Instead of writing value converters for most of the properties, I convert the BindingContext to underlying type and check the values of the properties in the OnBindingContextChanged event and right after that I build the UI with the relevant controls.
Do you think this is a bad way? Or is it ok?
I think it sounds quite counter-intuitive with regards to the MVVM model. Would you not be best binding the IsVisible property of the controls to a property determined in the ModelView?
e.g.
var label = new Label();
label.setBinding<ViewModel>(Label.IsVisibleProperty, vm => vm.IsLabelVisible, BindingMode.TwoWay);
You can then control the value of the IsLabelVisible property within the ViewModel instance.
One gotcha to consider is draw cycles and I would advise wrapping elements with toggled visibility states in Layout class.
Take a look at DataTemplateSelector pattern (similar to WPF):
http://forums.xamarin.com/discussion/comment/66502/#Comment_66502
Related
I have a very common problem, but I couldn't find any valid solution.
I want to create a Button able to contain more than a simple Label or Image. In fact, Xamarin Button exposes only Text and Image properties, but in my case I want to construct a more flexible set of controls (e.g. a StackPanel with a list of controls).
I implemented a ContentView acting as a Button after having added TapGestureRecognizer and it works from the pure functional point of view. What I don't like is the missing of all Visual States of a Button.
Therefore, I was thinking how to implement a Custom Renderer of a Button. I would like to expose a ContentPresenter BindableProperty and then set that property to the Button.Content (speaking in UWP terms) in the Renderer class. I think this could be a solution, the problem is that I don't know how to "cast" a Xamarin.ContentPresenter to a UWP.ContentPresenter. Do you have any idea about how to implement a Button able to contain any generic Content?
On my flex (flash builder 4) DataGrid - DataGridColumn , I have set a custom itemRenderer
itemRenderer="myComponents.EncounterDGItemRenderer".
My renderer is a Label
public class EncounterDGItemRenderer extends Label
I found that my tooltips (datatips) stopped working once I started using this custom renderer. I also found that I can set the tooltip on the label in the
override protected function updateDisplayList
by setting:
toolTip=data['addedDate'];
This works find, however the problem is I need to choose a different data field based on the column. I was hoping for something similar to how a DataGridColumn labelFunction works - where I have access to "column.headerText" or "column.dataField". However I only have access to the underlying data object, not the name of what is being displayed (unless I am missing something).
Is there a way in a data grid item renderer to know what the column header text is, or do you have a different approach?
So I came up with an answer that seems to work - I used a custom item renderer extending DataGridItemRenderer instead of extending 'Label'. Then, I set background = true and backgroundColor in there based on 'data' like I did above.
Then, the normal mxml show data tips / data tip field properties in the data grid columns work fine.
It makes sense though, this component should probably be upgraded to use Spark datagrid components - I am guessing that will allow background color and tool tips.
I have a flex 3 datagrid that is in a completely separate container from the object that I am trying to reference it from - i.e. the datagrid is in a vbox, and I am trying to set a property in the datagrid from a popup.
How do I access the datagrid from the popup?
I'd like to do something like:
myView.myDatagrid.resizableColumns = false;
Using cairngorm as a framework if that is of any help.
You'll have to explain your architecture better to get a specific answer. This answer may help as everything I said about running methods on another component, also applies to accessing properties.
One solution for you is to pass the DataGrid instance into the popup as an instance variable; then the PopUp will be able to change the DataGrid's properties easy.
When you add your popup, you need to listen for an event. Then your PopUp needs to dispatch an event that the parent can handle.
myPopup.addEventListener(SomeEvent.DISABLE_COLUMNS,disableResize);
and then in the parent component
public function disableResize(event:SomeEvent):void{
myDatagrid.resizableColumns = false;
}
This assumes a custom event called SomeEvent... you can actually just create a default Flash event and give it a name like
dispatchEvent(new Event("MyDisableResizeEvent"));
Assuming you've got a button in your popup:
<mx:Button click="{dispatchEvent(new Event('MyDisableResizeEvent'));}" label="Disable Resizing"/>
A combo box as an item renderer for a data cell in a Flex Datagrid has been demostrated at various blogs. What if that combo box has to have an external dataprovider that has to be set at the time of converting the renderer class to a ClassFactory.
Can this be done? Or is there a workaround?
Thanks in advance.
What if that combo box has to have an external dataprovider that has to be set at the time of converting the renderer class to a ClassFactory.
I don't think you meant to say what you said. But, at runtime, a renderer class is never converted into a ClassFactory. The renderer properties, such as itemRenderer or itemEditor are always factories. Now, the Flex compiler does some magic so that you specify the class name in MXML, it turns it into a ClassFactory. This happens at compile time.
I believe you mean that you want to set the dataProvider on the instance of the ComboBox as they are created by the ClassFactory. Is that correct? If so, you can extend the ClassFactory to do so.
You could also extend the ComboBox to be "dataProvider" aware. One approach is to build the remote service call to retrieve data directly into your extended ComboBox. Another might be to hard coded the dataProvider, Yet another might be to access some other application specific component for the data. One such example is using the Cairngorm ModelLocator.
Does that help?
I have an itemRenderer for a list where I'm just displaying items and their details respectively. I want to keep the details invisible and have a button,Show Details, in my main mxml file which when clicked would make the details visible.
So, my problem is in the clickHandler how can I access the details property within the itemRenderer from the main mxml?
Thanks in advance for your help
I would have a Boolean on the main which is what the itemRenderer keys off of. Accessing the itemRenderers of a list is not receommended because they are recycled, and operations cannot be guaranteed.
For an explanation see http://www.adobe.com/devnet/flex/articles/itemrenderers_pt1.html
There are a few ways to approach this.
One is to use a global Singleton object that contains the "ShowDetails" value. Every itemRenderer can access that object and change it's settings. Cairngorm's ModelLocator is one example of a singleton that is commonly used in this way. I believe swiz has something similar. You could also roll your own if needed.
You could try to extend the List class The List keeps itemRenderers in an array, which I believe is protected. You'll have to extend the List, and make this protected array public. Then you'll be able to access the list of itemRenderers and modify properties on them directly.
However, I'm not sure I would recommend either approach. An itemRenderer really should choose what to display based on the data it is displaying; not some global variable. Can you change the objects in your dataProvider and have the itemRenderer update accordingly? It is a third option; although I'm not sure if it is any better, or worse, than the previous two approaches.
You could have a variable in the DataProvider array called 'show' thats set to false. In the itemrenderer bind the visible property of the details component to data.show.
When the show button is pressed, traverse the dataProvider array, and set the 'show' property to true. This will work
Bish