MvvmCross : dynamic item template selection for MvxListView - android-layout

If I have a view with the following MvxListView definition:
<Mvx.MvxListView
android:layout_marginTop="10px"
android:textFilterEnabled="true"
android:choiceMode="singleChoice"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textSize="20dp"
local:MvxBind="ItemsSource Data; ItemClick LaunchCapabilityViewCmd"
local:MvxItemTemplate="#layout/itemtemplate1" />
Instead of hard coding MvxItemTemplate to itemtemplate1, it it possible to dynamically set this based on the type of data I want to display in this view? I am looking for similar functionality to WPF's DateTemplateSelector.
TIA.

You have to use a custom adapter to do this.
A few of the samples show how to use cell type selection. See:
polymorphic lists in https://github.com/slodge/MvvmCross-Tutorials/tree/master/Working%20With%20Collections
grouped lists in the session list views in https://github.com/slodge/MvvmCross-Tutorials/tree/master/Sample%20-%20CirriousConference
e.g. from PolymorphicListItemTypesView.cs
protected override View GetBindableView(View convertView, object source, int templateId)
{
if (source is Kitten)
templateId = Resource.Layout.ListItem_Kitten;
else if (source is Dog)
templateId = Resource.Layout.ListItem_Dog;
return base.GetBindableView(convertView, source, templateId);
}
For Android, there is also an optimisation which should be added to the existing polymorphic adapter samples - to include use of GetItemViewType for better convertView reuse - see https://github.com/slodge/MvvmCross/issues/333
This questions is linked to:
Several item templates in one listbox in mvvmcross Android
getViewTypeCount and getItemViewType methods of ArrayAdapter

Related

Custom selector challenges

I have a custom screen with a multiple custom selectors, which change what they select based on dropdown lists.
The solution I implemented is shown in a previous case:
Dynamically changing PXSelector in Acumatica (thanks).
My challenge is twofold:
1.) If the dropdown selection is "No Lookup", then I want the PXSelector Attribute to essentially be removed - leaving just a text entry. Not sure if this is even possible...
2.) If one of the selectors (let's say Projects) is selected, I'd like the selection of the following selector (let's say Tasks) to filter based on the Project selected.
Thanks much...
1) I think the only way to do this is to create your own attribute.
Something like that:
public class PXSelectorTextEditAttribute : PXSelectorAttribute
{
bool selectorMode;
public PXSelectorTextEditAttribute(Type type, bool selectorOn):base(type)
{
selectorMode = selectorOn;
}
public override void FieldVerifying(PXCache sender, PXFieldVerifyingEventArgs e)
{
if(selectorMode)
base.FieldVerifying(sender, e);
}
public static void SwitchSelectorMode(PXSelectorTextEditAttribute attribute, bool onOff)
{
attribute.selectorMode = onOff;
}
}
You will be able to turn on and off the 'selector' part of the attribute. With the field verifying turned off you will be able to put any value to the field just like in simple TextEdit field. However, the lookup button in the right end of the field still will be visible. I have no idea how to hide it.
2) This behavior can be implemented easily. You will need something like that(example based on cashaccount):
[PXSelector(typeof(Search<CABankTran.tranID, Where<CABankTran.cashAccountID, Equal<Current<Filter.cashAccountID>>>>))]
If you want to see all records when the cashaccount is not defined then you just modify the where clause by adding Or<Current<Filter.cashAccountID>, isNull>
Also don't forget to add AutoRefresh="true" to the PXSelector in the aspx. Without it your selector will keep the list of the records untill you press refresh inside of it.

WPFExtendedToolkit PropertyGrid Standard Values

I'm trying to display XmlElement's attributes in Xceed PropertyGrid. For that purpose I defined custom wrapper class. It wraps XmlElement, iterates over XmlAttributes and creates custom PropertyDescriptor for each XmlAttribute. All "virtual" properties' type is String. All works fine.
Now I want to have drop-down list of possible attribute values for every attribute that has restricted set of values. In Xceed's PropertyGrid, there is ItemsSourceAttribute for that. But it has to be applied as follows:
ItemsSourceAttribute(typeof(MyCustomItemsSource))
And here is the problem - I can not provide proper argument for MyCustomItemsSource constructor. What can I do about this?
It seems that there is another possibility - to define a TypeConverter, override GetStandardValues, and supply this converter to "virtual" property. But PropertyGrid just ignores this attribute.
How this simple task can be done with Xceed PropertyGrid?
Solved. I implemented custom editor
public class AttributeValuesEditor: Xceed.Wpf.Toolkit.PropertyGrid.Editors.ComboBoxEditor
{
protected override IEnumerable CreateItemsSource(PropertyItem propertyItem)
{
var property = propertyItem.PropertyDescriptor as XmlAttributePropertyDescriptor;
Debug.Assert(property!=null);
return property.GetCompletionValues();
}
}
Here, the context is passed into method in the form of PropertyItem. Now it is possible to differentiate between different attributes and return appropriate items.

Monotouch Dialog: Styling Elements

I'm using Dialog and would like to style all my cells. I have a background image, and in the samples I can see how you can use a StyledStringElement to use that image.
However, in real use some sections use other elements. For example the last element in one section is a RootElement - but it has no BackgroundUri property to set. The same would go for boolean elements.
I found this question - What's the best way to customise all monotouch.dialog TableViewCells to the same style (Background, etc..)? which is a similar question a year and a half back. The UIAppearance styling mentioned does exist for tablecells but does not work with MTDialog. krtrego's answer to this In monotouch.dialog can RootElement be easily styled? question purports to do the job, but no styling occurred when I implemented it.
Is there now any improved way to do this? Implementing my own 'styled' versions of these other control types would be a big effort and looking at the styledstringelement this is beyond my current skill level.
Here's an example of what I'd like to achieve (the shadow below the 'tags' cell, but the element is actually a RootElement with a set of radio options beneath it). Removing the default grey lines etc is easy enough, but putting a subtle shadow on the bottom cell of each section is what I cannot work out.
Many thanks!
PS. With a normal MTDialog screen with cell backgrounds and borders removed, there is a subtle white shadow/line beneath each section as it is. If I could just recolour that I'd be a long way to where I want to be...
Subclassing the element will let you style it via overriding the GetCell method, but that gets pretty tedious. The best solution I have come across is to to make a custom DialogViewController by subclassing it, and overriding the CreateSizingSource method with your own SizingSource and GetCell() methods using the images you want for each scenario of a cell (top, middle, bottom, alone). Its a bit of code and my example wont handle uneven rows, but it is the only solution I have seen that does not modify the MT.D source code.
Here is what you would override in your DialogViewController subclass:
public override Source CreateSizingSource(bool unevenRows)
{
return new CustomSource(unevenRows);
}
Then you would make a custom source class:
public class CustomSource : Source
{
public CustomSource(DialogViewController parent) : base (parent)
{
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var theCell = base.GetCell(tableView, indexPath);
if (RowsInSection(tableView, indexPath.Section) == 1) //use one with top and bottom rounded
{
theCell.BackgroundView = new UIImageView(Theme.CellBackgroundFull);
theCell.SelectedBackgroundView = new UIImageView(Theme.CellBackgroundFullActive);
} else if (indexPath.Row == 0) //top only
{
theCell.BackgroundView = new UIImageView(Theme.CellBackgroundTop);
theCell.SelectedBackgroundView = new UIImageView(Theme.CellBackgroundTopActive);
} else if (indexPath.Row+1 == RowsInSection(tableView, indexPath.Section)) // bottom only
{
theCell.BackgroundView = new UIImageView(Theme.CellBackgroundBottom);
theCell.SelectedBackgroundView = new UIImageView(Theme.CellBackgroundBottomActive);
} else //anything in the middle
{
theCell.BackgroundView = new UIImageView(Theme.CellBackgroundMiddle);
theCell.SelectedBackgroundView = new UIImageView(Theme.CellBackgroundMiddleActive);
}
return theCell;
}
}
Theme is just a static class that returns UIImages, similar to the example Field Service app from Xamarin. So here I have made 8 images total. 4 to represent the top, middle, bottom and alone for an element. Each has different rounded corners to appear correct. And then a "highlighted" version of each for when its touched.
The big drawback here is you have to do this for every different styled controller you would need. If you are ok with modifying the MT.D source code, you can get a different solution that will allow you to control it at the Section level here: http://fastchicken.co.nz/2012/05/20/earnest-debrief-visual-styles-in-ios-apps-uiappearence-custom-sections-in-monotouch-dialog/
Which has the same effect, but you only need to subclass Section for each different style, which makes including multiple styles in one Root easier. A pull request was made for this change, but Miguel favored the first solution instead, seen here: https://github.com/migueldeicaza/MonoTouch.Dialog/pull/180

Create and add f:selectItems to HtmlSelectOneRadio programmatically

I'm using JSF to create a questionnaire and therefore I need to create my whole xhtml pragmatically because there are different types of questions and the number of them is not predefined.
All I have is a h:panelGrid on my view and the rest is generated in my backing bean.
I have no problem creating HtmlOutputText and HtmlInputText. For that purpose I create them using getApplication e.g. like this:
getApplication().createComponent(HtmlOutputText.COMPONENT_TYPE);
and then add the component to my grid like this:
grid.getChildren().add(questionnumber);
where "grid" is my panelGrid element.
So I put my questions in a loop and based on the type of question from the db I decide what type of component to create. If the question is a normal text question I can easily use a HtmlInputText. But I have multiple choice questions too. Therefore I need to create SelectOneRadio menus and add SelectItems in them.
I can create a HtmlSelectOneRadio using the same createComponent method that I mentioned above. But I'm unable to add options to it (selectitem components). Is there a way that I can do this? Do we have a UIComponent for this that I am missing?
I found the solution myself. I had to use UISelectItems and add it to my SelectOneMenu like this:
final UISelectItem select = (UISelectItem) getApplication().createComponent(UISelectItem.COMPONENT_TYPE);
List<SelectItem> items = new ArrayList<SelectItem>();
for (int k = 0; k < options.length; k++){
items.add(new SelectItem(options[k]));
}
UISelectItems selectItems = new UISelectItems();
selectItems.setValue(items);
selectOneRadio.getChildren().add(selectItems);
grid.getChildren().add(selectOneRadio);

Xpages more fields (unlimited) at the click of a button

I would like to start with x no. of fields (in my app I have a pair of textual data field and numeric data field) on a xpage application (say 10 pairs) and then when the user clicks on "more field", I want more pairs to appear dynamically without a full refresh on the page, but would like unlimited no. of fields (as long as the page doesn't crash) and then I would like to submit the form and the data for all those fields. What's the best way to implement this?
Usually, fields are bound to a document data source using dot notation:
<inputText value="#{contact.firstName}" />
However, array notation is also supported:
<inputText value="#{contact['firstName']}" />
Because the field name in this latter syntax is being treated as a string, not as an implicit property of the bean, it can be dynamically computed. What I've found to be the easiest way to define these dynamic fields is to create a custom control for each of the basic types of fields, and define each as accepting the data source and the field name. So the field itself then ends up with a syntax similar to the following:
<inputText value="#{compositeData.dataSource[compositeData.fieldName]}" />
By using that syntax, a calculation of any complexity can be used to determine what field name to pass to the custom control. In the scenario you're attempting to accomplish, specifying an indexVar on the repeat control that surrounds the field pair would allow you to designate a field suffix for each... perhaps something like the following:
<xp:repeat indexVar="fieldSuffix" value="#{viewScope.rowCount}">
<xp:div>
<xc:dynamicInputText dataSource="#{contact}" fieldName="fullName_#{fieldSuffix}" />
<xc:dynamicInputNumber dataSource="#{contact}" fieldName="phoneNumber_#{fieldSuffix}" />
</xp:div>
</xp:repeat>
With this approach, you would end up with fields named "fullName_0", "fullName_1", etc., up to the limit specified in the viewScope. Typically, the only complication is ensuring that when an existing document is opened, the viewScope variable is set back to the correct limit. Another approach to that, of course, is actually saving the limit as another item on the document and binding the repeat value to it instead.
You also can have a look at the exercise 23 "Tablewalker". It doesn't do multiple fields but does Multi-value fields which might be better in terms of processing and storage (you can do an #Elements to find out how many are there in a document). The exercise is here:
http://www-10.lotus.com/ldd/ddwiki.nsf/dx/Tutorial-Introduction-to-XPages-Exercise-23
While the button only adds one row at a time, it is easy to adjust.
What you could do is have a Bean with 2 String values Label and Data and a managed bean that has a ArrayList of that object so inside of your repeat control you bind the repeat to the ArrayList and then bind your xp:inputText to rowData.Data and your xp:label to rowData.Label then when you want to add another 5 rows you just add However many more objects into the ArrayList then refresh your page, your data will still live in your arraylist and you will have 5 new Empty objects where you can add data.
public class Data {
private String label;
private String data;
public Data() {
}
//getters and setters
}
public class ManagedBean {
private ArrayList<Data> datalist; // add a managed property for this one so It will create a new one when needed.
// getters and setters
public addFiveMoreObjects() {
Data newItem;
for (int i=0; i<5; i++) {
newItem = new Data();
datalist.add(newItem);
}
}
}
<xp:repeat value="#{managedBean.datalist}" var="rowData">
<xp:text value="#{rowData.label}" />
<xp:inputText value="#{rowData.data} />
</xp:repeat>
<xp:button value="Add 5 More"> // call #{managedBean.addFiveMoreObjects}

Resources