How to create a If Else condition with xaml binding - xamarin.forms

I'm trying to create a XAML UI based on the condition.
<StackLayout Orientation="Horizontal">
<!--IF WorkEmailAddress != NULL && WorkEmailAddrress != ""-->
<!-- BEGIN IF -->
<Label Text="{Binding WorkEmailAddress}" Style="{StaticResource labelListItem}"></Label>
<Image HeightRequest="16" HorizontalOptions="End" VerticalOptions="Center" Source="arrow.png" Margin="0,0,15,0"></Image>
<!-- END IF -->
<!-- ELSE -->
<Label Text="Add new email" Style="{StaticResource labelLinkItem}">
</StackLayout>
Could one please let me know how to add a IF ELSE condition with in the XAML to dynamically create a UI based on the value returned from the backend.

You can't do this completely in XAML. Probably the best way to go is to add a bool property to your view model named HasWorkEmailAddress (I'm assuming you have one, and that's where WorkEmailAddress lives) which returns true if there's a non-null, non-empty value for WorkEmailAddress.
You can then bind the first label and Image's IsVisible property to this bool.
You can also create an InverseBooleanConverter, which will implement IValueConverter. The Convert method will simply take a bool and negate it, and return that value. Bind your second labels' IsVisible to the same bool, but specify the InverseBooleanConverter as the binding's Converter. It will then show only if the HasWorkEmailAddress returns false. The labels binding will look like this:
<Label IsVisible="{Binding HasWorkEmailAddress, Converter={StaticResource InverseBooleanConverter}}" />
If you don't want to write your own converter, one exists in the FreshEssentials Nuget package.
One last thing; if its possible for WorkEmailAddress to change while the page is being shown, you'll need to make sure you raise a PropertyChanged event for the HasWorkEmailAddress property, or your view will not change appropriately.

Related

Default start value for picker

I want to have blank value in my picker when I start the app(before I make selection).
Currently when I launch my app picker shows Value1 in the box. Here is my List that I bind with Picker:
private List<string> _PickerValueBind = new List<string>() {"Value1", "Value2"};
And the xaml:
<Picker ItemsSource="{Binding PickerValueBind}" HorizontalOptions="FillAndExpand" IsEnabled="{Binding PickerEnabledBind}" SelectedIndex="{Binding PickerIndexBind}">
<Picker.Behaviors>
<prism:EventToCommandBehavior
EventName="SelectedIndexChanged"
Command="{Binding IndexChangedBind}" />
</Picker.Behaviors>
</Picker>
I tried using Picker.Title but it didn't work as desired. Also tried adding empty item as first item but in the end I don't want user to have option to pick empty value.
Set value of PickerIndexBind = -1 in viewmodel

Xceed Datagrid won't bind to DataTemplate of Xceed control

I have the following DataTemplates defined. The TextBlock works the xctk:ShortUpDown does not. In fact whenever I use a control from another namespace it doesn't work (i.e. no data displayed or updated
<DataTemplate x:Key="intDataTemplate">
<TextBlock Text="{Binding StringFormat=\{0:F0\}}"/>
</DataTemplate>
<DataTemplate x:Key="hexDataTemplate">
<xctk:ShortUpDown ParsingNumberStyle="HexNumber"/>
</DataTemplate>
These are the column definitions. There is no CellEditorTemplate available.
<xcdg:Column FieldName="Coefficient" Width="75"
CellContentTemplate="{StaticResource hexDataTemplate}" ReadOnly="False"/>
<xcdg:Column FieldName="Measured" Width="75" CellHorizontalContentAlignment="Right"
CellContentTemplate="{StaticResource intDataTemplate}" />
There just doesn't seem to be a lot of example code out there. The columns are auto generated.
Any suggestions are appreciated.
The CellContentTemplate is for display purposes only. If you put a control meant for editing in it, such as a ShortUpDown, you will get weird results.
Editor controls should be defined in the CellEditor. Also, don't forget to set the CellEditorBinding to connect it to the underlying value.
<xcdg:CellEditor x:Key="hexCellEditor">
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<xctk:ShortUpDown Value="{xcdg:CellEditorBinding}" ParsingNumberStyle="HexNumber"/>
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
<xcdg:Column FieldName="Measured" CellEditor="{StaticResource hexCellEditor}" ... />

Windows Phone app: Binding data in a UserControl which is contained in a ListBox

I have an "AddressListBox" ListBox that contains "AddressDetails" UserControl items, as shown in the .xaml file extract below. The Addresses collection is defined as
ObservableCollection< Address > Addresses
and Street, Number, PostCode, City are properties of the Address class. The binding fails, when I use the "{Binding property}" syntax shown below. The binding succeeds, when I use the "dummy" strings in the commented-out code. I have also tried "{Binding Path=property}" syntax without success. Can you suggest what syntax I should use for binding the data in the user controls?
<ListBox x:Name="AddressListBox"
DataContext="{StaticResource dataSettings}" ItemsSource="{Binding Path=Addresses, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<!--
<usercontrols:AddressDetails AddressRoad="dummy" AddressNumber="dummy2" AddressPostCode="dummy3" AddressCity="dummy4">
</usercontrols:AddressDetails>
-->
<usercontrols:AddressDetails AddressRoad="{Binding Street}" AddressNumber="{Binding Number}" AddressPostCode="{Binding PostCode}" AddressCity="{Binding City}">
</usercontrols:AddressDetails>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You need to set the datacontext on the usercontrol to the item like this.
<usercontrols:AddressDetails DataContext={Binding}
...
</usercontrols:AddressDetails>
Now your other bindings should work correctly as they are relative to the item.

How can I get source property which is binded in Silverlight 4?

Here is an example:
<Grid x:Name="LayoutRoot">
<Control Value="{Binding Parent.Margins.Top, ElementName=LayoutRoot}"/>
</Grid>
I want to get type of the "Top" property to set correct value (null if it's nullable or "empty" parameter). How can I do this?
If you write an IValueConverter, and use that as the Converter for the Binding expression, then inside of the Convert/ConvertBack methods, you should get the value (typed as "object") and you can use GetType() on that to inspect it and decide how you want to act.

Silverlight4 Element Binding Weirdness

I'm a bit of a .net newbie and I've been working on my first big silverlight project. So pardon the lack of lingo and the length of the question. But my problem is as follows.
The project is being built according to the MVVM pattern ( in this case I'm using LightMVVM ). Most of the views contain ListBoxes. These listboxes need to handle multiple different types of data each of which has it's own visual look. After some poking around I decoded tp try this implementation for datatemplate selection:
http://silverscratch.blogspot.com/2010/04/changing-data-templates-at-run-time.html
Some of my items, however, have sub controls that need to talk to the viewmodel. From what I've been reading Commands with element bindings is the best ways to handle this.
So, for example:
<Grid x:Name="NavMainLayoutRoot" DataContext="{Binding Source={StaticResource NavMainViewModelDataSource}}" Margin="15,0,0,0">
....
<ListBox x:Name="MenuListBox" HorizontalAlignment="Left" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="White" ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource MainNavigationButtonStyle}" Padding="0" VerticalAlignment="Top" >
<ListBox.RenderTransform>
<CompositeTransform/>
</ListBox.RenderTransform>
<ListBox.ItemTemplate>
<DataTemplate>
<xxxControls:SelectableContentControl TemplateName="{Binding Path=Type}" Content="{Binding Details}" IsTabStop="{Binding IsHitTestEnabled}">
<xxxControls:SelectableContentControl.Templates>
<DataTemplate>
<local:GenericItem />
</DataTemplate>
<DataTemplate x:Name="navbutton">
<local:MainNavItem />
</DataTemplate>
</xxxControls:SelectableContentControl.Templates>
</xxxControls:SelectableContentControl>
</DataTemplate>
</ListBox.ItemTemplate>
....
And MainNavItem, simplified is:
<Grid x:Name="NavItemRoot" VerticalAlignment="Top" Margin="0,0,0,0">
<Button Content="{Binding Label}" VerticalAlignment="Top" Style="{StaticResource MainNavItemButtonStyle}" HorizontalAlignment="Left" Margin="5,0" Command="{Binding DataContext.NavButtonClick, ElementName=NavMainLayoutRoot}"/>
</Grid>
The problem is that this didn't work. So for grins I went ahead and copy and pasted the code for the MainNavItem directly into the tag and like magic it started working.
Since I reuse a lot of these item templates all over the application, having them in nice contained external files is very nice and not something I want to give up.
(( Thinking about it, this example is not the best, suffice it to say that some of these data templates contain multiple controls and I can't just use selectedItem on the listbox to handle the selected events. ))
So any suggestions are welcome. What's the best practice here?
My first thought is that something in your MainNavItem user control is setting its DataContext to something else. If you don't set the DataContext it should automatically pick it up from the current item in your MenuListBox.
You can try creating a test value converter and putting a breakpoint in it to check what the data context is at runtime.
public class TestConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.WriteLine("TestConverter.Convert(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
value, targetType, parameter, culture);
return value; // put break point here to test data binding
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.WriteLine("TestConverter.ConvertBack(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
value, targetType, parameter, culture);
return value;
}
}
And modify your MainNavItem to look like this in order to break in the TestConverter at runtime.
<UserControl.Resources>
<ResourceDictionary>
<TestConverter x:Key="TestConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="NavItemRoot" DataContext="{Binding Converter={StaticResource TestConverter}}">
<Button Content="{Binding Path=Label, Converter={StaticResource TestConverter}}" />
</Grid>
This will help you determine the issue with data binding.
I suspect that the problem with your command is that you're using element-to-element data binding to attempt to bind to an element that is outside of the user control you're currently within. This won't work. Instead, try setting up your NavMainViewModelDataSource static resource in App.xaml, then you can bind directly to it from your user control.
<Button Content="{Binding Label}" Command="{Binding Path=NavButtonClick, Source={StaticResource NavMainViewModelDataSource}}" />

Resources