ValueConverter - binding to self - binding

I need to bind a label to a composite value - made up of a couple of values in the model. I'm trying to use a ValueConverter to do so, but I can't figure out how to pass the object itself to the ValueConverter. Here's my code:
in XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp;assembly=MyApp"
x:Class="MyApp.SavedDetailsPage">
<ContentPage.Resources>
<ResourceDictionary>
<local:DetailsConverter x:Key="detailsCvt" />
</ResourceDictionary>
</ContentPage.Resources>
...
<Label Text="{Binding ???, Converter={StaticResource detailsCvt}}" FontSize="Small" TextColor="Gray" />
...
in DetailsConverter.cs:
class DetailsConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
MyModel myModel = (MyModel)value;
return (myModel.FirstName + " " + myModel.LastName);
}
...
I tried using '.' for binding to self, but that didn't work.
I found a way around it by adding a .This property to MyModel, that gives access to the object itself, so I can pass 'This' in the XAML binding, but not sure if that's the best way.
Thanks in advance!

to bind to the ViewModel, you can use one of the following syntax
{Binding}
{Binding .}
{Binding Path="."}

Related

Binding issue in custom Xamarin.Forms control

I have a strange problem with bindings on a custom control. I created a custom toolbar:
public partial class TopToolbar
{
public static readonly BindableProperty BackCommandProperty =
BindableProperty.Create(nameof(BackCommand), typeof(ICommand), typeof(TopToolbar), propertyChanged: BackCommandChanged);
public ICommand BackCommand
{
get => (ICommand) GetValue(BackCommandProperty);
set => SetValue(BackCommandProperty, value);
}
public TopToolbar()
{
InitializeComponent();
}
// for debug purposes only
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
Debug.WriteLine(BindingContext);
}
// for debug purposes only
private static void BackCommandChanged(BindableObject bindable, object oldvalue, object newvalue)
{
Debug.WriteLine($"old: {oldvalue}, new: {newvalue}");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Core.Controls.TopToolbar"
x:Name="TopToolbarView"
BindingContext="{x:Reference TopToolbarView}"
Orientation="Vertical">
<StackLayout Orientation="Horizontal"
HorizontalOptions="FillAndExpand"
<Image Source="{StaticResource Image.Toolbar.LeftArrow}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BackCommand}" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
</StackLayout>
I use it on a page in this way:
<pages:ContentPage.Content>
<StackLayout BackgroundColor="{StaticResource LightGrayColor}"
Spacing="0"
Padding="0">
<controls:TopToolbar Title="Master Data" BackCommand="{Binding MyBackCommand}" />
BindingContext of the page is a view model:
public class MyCustomersPageModel
{
public RelayCommand MyBackCommand { get; set; }
public MyCustomersPageModel()
{
MyBackCommand = // command creation;
}
}
From the debugging I know that BindingContext of a control is set (OnBindingContextChanged called) properly to itself (TopToolbar object) twice - first time when there's no child views and second time after they are added. I've checked that BindingContext is correctly propagated in all child controls.
Unfortunately the BackCommand is not bind at all. The setter of the TopToolbar.BackCommand is not called even once.
Interestingly when I replace setting the BindingContext on a control to setting the Souce directly in bindings everything works fine:
<?xml version="1.0" encoding="UTF-8"?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Core.Controls.TopToolbar"
x:Name="TopToolbarView"
Orientation="Vertical">
<StackLayout Orientation="Horizontal"
HorizontalOptions="FillAndExpand"
<Image Source="{StaticResource Image.Toolbar.LeftArrow}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference TopToolbarView}, Path=BackCommand}" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
</StackLayout>
Any clue what I do wrong?
It is working as expected. I would recommend using Source.
In first case, when you set BindingContext on TopToolbar to itself, then I would imagine this would be the sequence of events:
Custom control is constructed, BindingContext is assigned to self through reference.
Page instance is created, control is added to it.
When page's BindingContext is set, through power of property inheritance, all it's child controls' BindingContext is updated.
At this point your custom control's BindingContext is still referencing itself as value-propagation doesn't override manually set context.
Therefore, binding <controls:TopToolbar BackCommand="{Binding MyBackCommand}" fails, as this binding will try to look for MyBackCommand on it's binding-context which is TopToolbar.
But, in second case, when you specify binding Source as TopToolbar on Tapped command, then this should be the sequence of events:
Custom control is constructed, BindingContext is null.
Page instance is created, control is added to it.
When page's BindingContext is set, through power of property inheritance, all it's child controls' BindingContext is updated, including your custom control.
At this point your custom control's BindingContext is now referencing MyCustomersPageModel. So binding in <controls:TopToolbar BackCommand="{Binding MyBackCommand}" is appropriately set.
Now the Tapped binding doesn't care about BindingContext as it's source is explicitly specified, which is parent control TopToolbar - whose BackCommand in turn is bound to the view model's command. Hence, the view-model command is now bound to gesture-recognizer's Tapped command. And it works!

How to dynamically add listheaders and listcells in ZK

I am totally new in ZK. I need to create N listheaders and N listcells in my zul file. But I do not know how to do it from my java controller and I am not using MVVM.
The problem would be something like:
#Wire
private Window idWindow;
private Listheader header;
private Listcell item1;
#Override
public void onCreate(Event event) {
header.setLabel("laaaa");// It would set just one header but I can have many (N headers) and same for items
}
<zk>
<window id="idWindow" title="nameWindow" apply="controller.java" border="normal" closable="true" sizable="true" maximizable="true" maximized="true" height="85%" width="150%" style="overflow:auto;">
<!-- CONTINUES -->
<listbox id="mainList" hflex="1" vflex="1">
<listhead>
<listheader id="header" label="A" />
<listheader id="header1" label="B" />
<listheader id="header2" label="C" />
....
<listheader id="headerN" label="N" />
</listhead>
<listitem>
<listcell id="item1" label="A"/>
<listcell id="item2" label="B"/>
<listcell id="item3" label="C"/>
....
<listcell id="itemN" label="D"/>
</listitem>
</listbox>
<!-- CONTINUES -->
</window>
</zk>
You can leave the listhead empty in the zul, wire it into your controller and create the listheaders there. The important step is to ask the listbox for its listhead, and append the listheaders to it. For the cells, give your listbox a renderer that creates them for each item if you use a model to give your list data.
Your zul will be much shorter:
<zk>
<window ... >
<listbox id="mainList" hflex="1" vflex="1">
<listhead />
</listbox>
</window>
</zk>
Then in your controller, you create the header in doAfterCompose and attach the renderer:
#Wire
private Listbox mainList;
#Override // This method should be specified by a composer super class
public void doAfterCompose(Component comp)throws Exception
{
super.doAfterCompose(comp);
mainList.setModel(someModelWithYourData);
// create listheaders (manually/in for-loop/based on data...)
Listhead head = mainList.getListhead();
head.appendChild(new Listheader("A"));
...
// attach renderer
mainList.setItemRenderer(new ListitemRenderer<Object>() // use proper data type instead of Object
{
#Override
public void render(Listitem item, Object data, int index)
throws Exception
{
item.appendChild(new Listcell("a"));
...
}
});
}
There is also an example on zk's developer sites: https://www.zkoss.org/wiki/ZK_Developer%27s_Reference/MVC/View/Renderer/Listbox_Renderer
In case you cannot use a model, you could also append the listitems in the zul or in the controller, and then create the listcells:
for (Component child : mainList.getChildren())
{
if (child instanceof Listitem)
{
Listitem item = (Listitem) child;
// do the same as in the renderer
}
}

Struts 2 Populate select drop list

Hi i want to populate the select drop down list with some value. I use Struts 2, Tiles and JSP. I initialize my list in the Action class but i am still getting the following error :
Caused by: tag 'select', field 'list', name 'anneeResultat': The requested list key 'anneesResultatsList' could not be resolved as a collection/array/map/enumeration/iterator type. Example: people or people.{name} - [unknown location]
Here is my code in Action class:
private AnneeResultat anneeResultat;
private Map<String, String> anneesResultatsList = new HashMap<String, String>();
public Map<String,String> getAnneesResultatsList() {
this.anneesResultatsList.put("2005","2005");
this.anneesResultatsList.put("2006","2006");
this.anneesResultatsList.put("2007","2007");
this.anneesResultatsList.put("2008","2008");
this.anneesResultatsList.put("2009","2009");
this.anneesResultatsList.put("2010","2010");
this.anneesResultatsList.put("2011","2011");
return this.anneesResultatsList;
}
public void setAnneesResultatsList(Map<String,String> anneesResultatsList) {
this.anneesResultatsList = anneesResultatsList;
}
return SUCCESS;
}
My struts.xml file contains :
<action name="ChoixAxes" class="fr.si2m.occ.web.actions.ChoixAxesAction"
method="execute">
<result type="tiles">choixAxes.tiles</result>
</action>
My jsp is here:
<s:set name="theme" value="'xhtml'" scope="page" />
<s:form action="ChoisirAxes" name="choices" id="choices">
<s:select name="anneeResultat" label="Année de résultats" list="anneesResultatsList"></s:select>
<s:radio label="Listes nominatives" name="listesNominatives" list="#{'1':'Oui','2':'Non'}" value="2" />
<s:submit value="Calculer provisions" name="calculerProvisions"/>
<s:reset value="Annuler" />
<input type="button" value="Critères sauvegardés" id="criteresSauvegardes"/>
</s:form>
Some one could help me please ?
I have this problem since yersterday.
Prepare interceptor calls prepare() on actions which implement
Preparable. This interceptor is very useful for any situation where
you need to ensure some logic runs before the actual execute method
runs.
Your action should extend Preparable interceptor and override prepare() method, give the pre populated data.
Struts2 Prepare Interceptor
Put AnneesResultatsList in session
Map session=ActionContext.getScession();session.put("list",AnneesResultatsList );
<pre>
s:select name="anneeResultat" label="Année de résultats" list="%{#session.list}""></s:select>
</pre>
actually it is,
Map session = ActionContext.getcontext().getsession();
session.put("key",list);
<s:select list="%{#session.key}">

Silverlight 4 Tooltip Visibility Binding

I'm trying to bind tooltip visibility in XAML and I'm running into a confusing problem where my visibility binding works fine on other controls but not on the tooltip.
I have a form with a submit button that is disabled when the required fields haven't been entered. When the button is disabled I want a tooltip on it with a relevant message. When it's enabled there is no need for the tooltip. To accomplish this I place the button in a transparent border and set the tooltip on the border since a tooltip on the button itself will never show when it's disabled. However, visibility binding to the tooltip fails and it seems I can only change the visibility in code-behind. I can use the exact same binding on visibility for various controls (in the example below I use it on a TextBlock as well). If I apply the exact same binding in code-behind, it works fine. Why doesn't this work in XAML?
XAML
<UserControl.Resources>
<local:VisibilityConverter x:Key="visibilityConverter"/>
<local:VisibilityConverter x:Key="reversedVisibilityConverter" IsReversed="True"/>
</UserControl.Resources>
<StackPanel Background="White"
Width="310">
<TextBlock Text="Using XAML binding for tooltip visibility..."
FontWeight="Bold"/>
<CheckBox x:Name="cbEnable"
Content="Enable Submit Button"/>
<Border Background="Transparent"
Margin="0,10,0,0">
<ToolTipService.ToolTip>
<!-- This has the same binding as the 2nd TextBlock below, it should be visible when cbEnable is NOT checked and collapsed when it is checked -->
<ToolTip Content="Submit Button Is Disabled"
Visibility="{Binding IsChecked, ElementName=cbEnable, Converter={StaticResource reversedVisibilityConverter}}"/>
</ToolTipService.ToolTip>
<Button Content="Submit"
IsEnabled="{Binding IsChecked, ElementName=cbEnable}"/>
</Border>
<!-- This TextBlock is visibile when cbEnable is checked -->
<TextBlock Text="Submit Button is enabled"
Visibility="{Binding IsChecked, ElementName=cbEnable, Converter={StaticResource visibilityConverter}}"/>
<!-- This TextBlock is visibile when cbEnable is NOT checked (same as ToolTip binding above -->
<TextBlock Text="Submit Button is disabled"
Visibility="{Binding IsChecked, ElementName=cbEnable, Converter={StaticResource reversedVisibilityConverter}}"/>
<TextBlock Text="Using code-behind binding for tooltip visibility..."
FontWeight="Bold"
Margin="0,20,0,0"/>
<CheckBox x:Name="cbEnable2"
Content="Enable Submit Button"/>
<Border Background="Transparent"
Margin="0,10,0,0">
<ToolTipService.ToolTip>
<ToolTip x:Name="toolTip2"
Content="Submit Button 2 Is Disabled"/>
</ToolTipService.ToolTip>
<Button Content="Submit 2"
IsEnabled="{Binding IsChecked, ElementName=cbEnable2}"/>
</Border>
<TextBlock Text="Submit Button 2 is enabled"
Visibility="{Binding IsChecked, ElementName=cbEnable2, Converter={StaticResource visibilityConverter}}"/>
<TextBlock Text="Submit Button 2 is disabled"
Visibility="{Binding IsChecked, ElementName=cbEnable2, Converter={StaticResource reversedVisibilityConverter}}"/>
</StackPanel>
Code-behind:
public partial class MainPage : UserControl {
public MainPage() {
InitializeComponent();
toolTip2.SetBinding(ToolTip.VisibilityProperty, new System.Windows.Data.Binding("IsChecked") {
Source = cbEnable2,
Converter = new VisibilityConverter() { IsReversed = true }
});
}
}
VisibilityConverter:
public class VisibilityConverter : IValueConverter {
public bool IsReversed { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
bool isVisible = System.Convert.ToBoolean(value, CultureInfo.InvariantCulture);
if (IsReversed) {
isVisible = !isVisible;
}
return (isVisible ? Visibility.Visible : Visibility.Collapsed);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
bool isVisible = ((Visibility)value == Visibility.Visible);
if (IsReversed) {
isVisible = !isVisible;
}
return isVisible;
}
}
Well, I don't know why this fixed it but here is what I did: I renamed the property in my ViewModel. Yep, I know. Seems ridiculous. I changed the property from IsWaitingVisible to WaitingVisibility. I got the idea because I changed the ViewModel property from a bool to text and then bound it to a temporary, visible TextBlock. It would not show the value the same way a different property in the same ViewModel would. That was just crazy so I renamed the property to something else and voila! The text started appearing in the UI. Then, I reconnected the visibility property of the grid (and changed my VisibilityConverter to work with strings instead of bool) and everything worked.
I guess for the purposes of science, I should change the property name back to IsWaitingVisible and see if it breaks. If so, I will have to conclude that this is a hard bug in SL 5.
This kind of flakiness just scares me when I think about building reliable apps in Silverlight.

How to get value in a textbox from a JSF page to a Java Class?

I already created the bean, and it gets the value from the textbox, my problem is how can i pass it to another java class?
Just pass it as method argument the usual Java way. You can do it in the action method.
E.g.
<h:form>
<h:inputText value="#{bean.input}" />
<h:commandButton value="Submit" action="#{bean.submit}" />
</h:form>
with
private String input; // +getter +setter
public void submit() {
YourAnotherClass yourAnotherClass = new YourAnotherClass();
yourAnotherClass.process(input);
}

Resources