Bind a List<string> to MvxListView in MvxActivity - mvvmcross

I want to bind a List to MvxListView which is defined as property in one of my ViewModel class/
How can I do this?

In the markup .axml u define the ItemsSource
<Mvx.MvxListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20dp"
local:MvxBind="ItemsSource MyStringList"/>
MyStringList is the List Property in your Viewmodel. INotifyPropertyChanged also needs to be implemented and the Activity itself must know it's viewmodel, there are lot of examples here

Related

Iterate through DataContext items without casting it to a viewmodel type

Is their a way to access Items contained in a DataContext without having to explicitly cast it to this ViewModel.
Let's say I'm binding a DataContext on an MvxFrameControl view, then I obtain this DataContext in code-behind once it is binded. It will look like an anonymous object containing a list of Items that are known as the children of this ViewModel. Can I swiss-bind these items, or some properties of this DataContext to another object, and so on?
I.e.
this.DelayBind(() =>
{
var data = DataContext;
// It looks like data contains something called "Items" with a list of children viewModels.
});
Can I access DataContext.Items[0], or at least DataContext.Items, and bind it to an observable collection? Then finally swiss-bind some Items to views (MvxFrameControls) on their DataContext?
So, summary: I'm curious if there is a way to work in code-behind with DataContext and its content so I could create a generic MvxFrameControl that would dispatch the data to custom views based on swiss-binding.
I have ViewModels containing lists of lists, and I want to handle a lot of situations in code-behind as I've experienced a lot of memory problems with MvxListViews containing MvxListViews.
[Edit]
This is actually what I was doing in my code that led me to think I should completely redefine how bindings are done. I'll write a minimal fake axml:
// Warning to anyone: this is a fake layout, don't use that
view_myactivity_layout.axml :
<LinearLayout>
<MvxListView
android:MvxItemTemplate="#layout/food_category_item"
local:MvxBind="ItemsSource FoodCategories" />
</LinearLayout>
food_category_item.axml:
<LinearLayout>
<TextView
local:MvxBind="Text Category" />
<MvxListView
android:MvxItemTemplate="#layout/list_of_food_for_a_category_item"
local:MvxBind="ItemsSource FoodList" />
</LinearLayout>
list_of_food_for_a_category_item.axml:
<LinearLayout>
<TextView
local:MvxBind="Text NameOfThatFood" />
<MvxListView
android:MvxItemTemplate="#layout/list_of_colors_for_that_food_item"
local:MvxBind="ItemsSource FoodList" />
</LinearLayout>
[Etc...]
Nesting binded controls works well, but there are tons of GC happening when scrolling. So that's why I was thinking about making my own binding pattern using reflection for this case.

MVVMCross ValueConverter Parameter

Hello MVVMCross community,
My question is about ValueConverters parameters:
Is there any way to pass a variable to a Value Converter rather than a constant value as a ConverterParameter?
Something like:
<EditText
android:id="#+id/editPrice"
...
local:MvxBind="Text Price; Enabled IsPriceEnabled; BackgroundColor IsPriceEnabled, Converter=Enabled2MvxColor, ConverterParameter=Price"/>
or even pass the whole object for example:
<EditText
android:id="#+id/editPrice"
...
local:MvxBind="Text Price; Enabled IsPriceEnabled; BackgroundColor IsPriceEnabled, Converter=Enabled2MvxColor, ConverterParameter=editPrice"/>
TIA,
When using Windows/XAML IValueConverter you can't really pass data-bound entries into the value converter parameter.
However, using the Tibet binding extensions within MvvmCross, you should be able to do this if you use the form:
local:MvxBind="BackgroundColor Enabled2MvxColor(IsPriceEnabled, Price)"
For more on this - and on whole object binding, see https://github.com/MvvmCross/MvvmCross/wiki/Databinding
I had to do something similar couple of days ago: it's rather convoluted:
<controls:OptionItemControl
ItemTitle="{Binding Path=AccountSettings, Converter={StaticResource ContentItemConverter}, Mode=OneTime,
ConverterParameter=DataRoaming.Text}"
ItemInfo="{Binding Path=AccountSettings, Converter={StaticResource ContentItemConverter}, Mode=OneTime,
ConverterParameter=DataRoaming.Info}"
ItemValue="{Binding AccountSettings.DataRoaming, Mode=TwoWay}"
/>
So my ViewModel has a property AccountSettings, which is a class that has another property DataRoaming, which has several properties like .Text, .Info
I am sure there is much easier way to do what I needed it to do, but I wanted to get from using magic string; I didn't get it at the end, but at-least this makes it easier for me to read and figure out.
so in converter I get the parameter, split it; then from value type and I can navigate through the properties and get the actual value from the class. Of course I could have as well called a method.
Hope this might give you some ideas.

MvvmCross Binding Image with ImageButton

I try to bind Image Url to image button
<ImageButton
android:id="#+id/activity_image"
android:clickable="true"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="4dp"
android:layout_alignParentLeft="true"
local:MvxBind="ImageUrl Type, Converter = Activity" />
But his does not work. If I change ImageButton to Mvx.MvxImageVIew, it will work. I also tried Mvx.MvxImageButton (If this exists), it show error.
I want to know if there is way to bind image of a imagebutton
MvvmCross can only bind existing C# Properties.
MvxImageView has an ImageUrl property - ImageButton doesn't.
To get the functionality you require:
You could just use an MvxImageView class with a Click event?
You need create your own ImageButtonEx class as a subclass of ImageButton - but which adds an ImageUrl property. For how to do this, see N=18 in http://mvvmcross.wordpress.com along with the source code for MvxImageView - https://github.com/slodge/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Binding.Droid/Views/MvxImageView.cs

if we can access outer function from rendered item by using "outerdocument" object then cant we access inner function from outside.?

These are the scripts under same application first one is under application and second is under dataGrid. from first script through outerClick() i am accessing a inner() function in itemrenderer. Well I can easily access the function outer() from innerClick() by outerDocument object but what_to_use to access inner() function in itemrenderer from outerClick() function. i tried with mx:component id"" and also class="" but it is not able to identify functions under itemrenderer.
<mx:Script>
<![CDATA[
public function outer():void{
Alert.show("Hi i am outer object");
}
public function outerClick():void{
what_to_use.inner();
}
]]>
</mx:Script>
This below item is rendered under data grid.
<s:itemRenderer>
<mx:Component>
<s:GridItemRenderer>
<fx:Script>
<![CDATA[
public function innerClick():void{
outerDocument.outer();
}
public function inner():void{
Alert.show("Hi i am inner");
}
]]>
</fx:Script>
<s:CheckBox id="sel" selected="{data.checked=sel.selected}" change="{data.checked}" click="innerClick()"/>
</s:GridItemRenderer>
</mx:Component>
</s:itemRenderer>
if we can access outer function from rendered item by using
“outerdocument” object then cant we access inner function from
outside.?
You seem to have a distinct misunderstanding of what itemRenderers are. An itemRenderer is a component definition, sort of like creating your own class. since you are using your the 'outerDocument' reference, you are creating your own class in-line / embedded within another class.
An instance of your custom itemRenderer class is created for every visible item in your List based class; so your own class is created multiple times, which means there is more than 1 instance of your itemRenderer function. How would Flex know which itemRenderer instances you want to call the function on? In fact it can't.
That is why you can call up, but you cannot call down.
If you need to make changes inside the itemRenderer, you should do so by changing the data elements of the dataProvider.
For all intents and purposes, I recommend against using outerDocument too. It is a break in encapsulation. A component should never try to access its' parent; because that often introduces an unneeded dependency to your component, limiting reuse. The proper way to "communicate up" is to dispatch an event from the itemRenderer and listen for it in the parent class.
This concept is covered briefly on the answer to one of your previous questions.

Three way binding in MXML custom component (using only mxml)

I'm trying to do this using only mxml, no <script> tags, although I don't necessarily need a solution that's only mxml. It was more of an educational exercise to see if I could do it all in mxml.
I have a custom component that has a slider and textinput and their value/text properties are bound together. I'm surfacing a few properties of the slider in my component so that it can sort of be treated like a slider.
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" verticalAlign="middle" horizontalGap="0">
<mx:int id="value">{slider.value}</mx:int>
<mx:int id="minimum">0</mx:int>
<mx:int id="maximum">100</mx:int>
<mx:int id="tickInterval">25</mx:int>
<mx:Array id="labels">['0%','50%','100%']</mx:Array>
<mx:HSlider id="slider" liveDragging="true" snapInterval="1"
value="{int(input.text)}"
minimum="{minimum}"
maximum="{maximum}"
tickInterval="{tickInterval}"
labels="{labels}"/>
<mx:Spacer width="25"/>
<mx:TextInput id="input" restrict="0-9" text="{slider.value}" maxChars="3" width="30"/>
<mx:Label text="%"/>
</mx:HBox>
Notice the slider's VALUE property is bound to the input field's TEXT property, and vice versa. A two-way binding. This lets the user slide the thumb or type in the input field to select a value and they stay in sync with each other.
Also, the component's VALUE property is bound to the slider's VALUE property so that the value of this component will always contain the value of the slider (so that the component can be used like a slider).
The slider's properties are also bound to the component's properties (min, max, tick marks)
The problem is that I want to initialize the value of the slider from the value of the component, but the slider's value is already bound to the textinput. Can I also bind it to the component?
My application will have something like this:
<local:mycomponent minimum="20" maximum="80" labels="['20','50','80']" value="40"/>
A few things I tried that didn't work:
(1) I had an initialize handler.
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" initialize="slider.value=value">
This worked if my app had
myslider.value = 40;
but didn't work if I had
<local:mycomponent value="40"/>
(2) I tried a creationComplete handler
(3) I tried mx:binding
<mx:Binding source="slider.value" destination="this.value"/>
It seems like I'm missing something simple.
Note the curly brackets:
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" initialize="{slider.value=value}">
In the brackets, there may be any code. Without them, there can only be event handler (function).