Xamarin: Hide the button if condition is false - xamarin.forms

I am new to Xamarin Forms.
I want to know how to hide a button if a specific condition is false.
ex: I need to hide the submit button until the text field has a value.
(if the text field is null, cannot click the submit button)
this is my .xaml code
<Entry Grid.Row="0"
Margin="10,10,10,20"
x:Name="ground_area"
Grid.Column="1"
MaxLength="5"
HorizontalOptions="Center"
Placeholder="area"
FontSize="18"/>
<Button x:Name="avg_nut"
Text="Submit"
Grid.Row="5"
VerticalOptions="Center"
Margin="40,0,20,50"
Style="{StaticResource buttonStyle}"
Clicked="submit_click">
</Button>

Hey you can use the property of the button IsEnabled="{Binding booleanProperty}" and in your view model you can manipulate the value of this property depending in what you want
I recommended you to use View Model instead of Code Behind is not that hard learn how works MVVM (Model View ViewModel)
That's my advice.
I hope this can solve your problem

Use Trigger:
<Entry x:Name="ground_area"/>
<Button Text="Submit">
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding Text.Length, Source={Reference ground_area}, FallbackValue=0}" Value="0">
<Setter Property="IsVisible" Value="False"/>
</DataTrigger>
</Button.Triggers>
</Button>
Also, check IsEnabled property, it's better than hiding the control.

Related

Customize look of selected element

Is there any possibility to customize the look of the active/selected item in the indicator view? Using Data Template Selector or something?
Data template changes every single item.
My goal is to reach this effect:
Try using trigger when color changes of your view at that time increase view's width or you may use view's PropertyChanged event to detect changes in view. I had a similar kind of requirement today and below code worked for me.
<IndicatorView
x:Name="introductionIndicator"
Grid.Row="2"
HorizontalOptions="Center"
IndicatorColor="{StaticResource PrimaryLightGrayColor}"
SelectedIndicatorColor="{StaticResource PrimaryYellowColor}">
<IndicatorView.IndicatorTemplate>
<DataTemplate>
<BoxView
CornerRadius="10"
HeightRequest="6"
WidthRequest="20">
<BoxView.Triggers>
<Trigger TargetType="BoxView" Property="BackgroundColor" Value="{StaticResource PrimaryYellowColor}">
<Setter Property="WidthRequest" Value="30" />
</Trigger>
</BoxView.Triggers>
</BoxView>
</DataTemplate>
</IndicatorView.IndicatorTemplate>
</IndicatorView>
result:

Xamarin Forms Transalted Button click

I am creating a rounded menu with Xamarin Forms as Below.
The accent color is my Grid. Then I translatex and trnaslatey the buttons.
My issue is that the click button is not raised. I have also tried on the gesture recognizer of my stack panel. Same result.
The part of the code is below:
<Grid BackgroundColor="Accent" Margin="0,0,0,10" VerticalOptions="End" HorizontalOptions="Center">
<StackLayout x:Name="cat" TranslationX="-109" TranslationY="-102"
>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="catBtn_Clicked"/>
</StackLayout.GestureRecognizers>
<Button Clicked="catBtn_Clicked" WidthRequest="60"
HeightRequest="60"
FontSize="35"
CornerRadius="30" HorizontalOptions="Center"
BackgroundColor="{StaticResource RedColor}"
TextColor="White"
Text="{ x:Static local:GrialIconsFont.Calendar }"
FontFamily="{ StaticResource IconsFontFamily }">
</Button>
<Label Text="{extensions:Translate Hello}" HorizontalOptions="Center"/>
</StackLayout>
Make sure that your button is placed inside superView's bounds,
If a button is placed outside superView's bounds, the button will not clickable.
You use TranslationX="-109" and TranslationY="-102" will make the button out of the bounds of StackLayout, so it won't response to the click event. You can add backgroundColor to stacklayout to see its bounds.
I would suggest you to add those buttons or labels directly to Grid and use absolute-layout, relative-layout or other layout to fix their positions.
There are also some examples in Github you can refer, such as CircleButtonMenu, Xamarin.Forms-RadialMenu

Xamarin Forms ToolbarItem doesn't change IsEnabled from XAML

I'm facing a problem with ToolbarItem and IsEnabled property when trying to turn it on/off from XAML using triggers. ToolbarItem doesn't support triggers, so what I do is to create a Button (a hidden one) which supports triggers and then bind Button.IsEnabled to ToolbarItem.IsEnabled; here is the sample code:
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="tlbSave" Text="Save" Clicked="Handle_Clicked">
<ToolbarItem.IsEnabled>
<Binding Source="{x:Reference btnTest}" Path="IsEnabled" />
</ToolbarItem.IsEnabled>
</ToolbarItem>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout Padding="10" VerticalOptions="CenterAndExpand">
<Entry x:Name="txtTest" HorizontalOptions="FillAndExpand" />
<Button x:Name="btnTest" Text="HIDDEN" IsEnabled="false" HorizontalOptions="FillAndExpand">
<Button.Triggers>
<MultiTrigger TargetType="Button">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference txtTest}, Path=Text.Length,
Converter={convert:IsPositiveIntegerConverter}}" Value="true" />
</MultiTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiTrigger>
</Button.Triggers>
</Button>
</StackLayout>
</ContentPage.Content>
If you try this piece of code you will see how btnTest gets enable/disable when txtTest.Text has some value. But it isn't affecting tlbSave.IsEnabled property.
However, this work perfect in code behind when I set tlbSave.IsEnabled into btnText.PropertyChanged EventHandler
btnTest.IsVisible is false, I'm just showing it up for testing purposes.
Any idea about how to deal with this?
This is because of the IsEnabled property of ToolbarItem is read-only.
If you just set IsEnabled property of a toolbar item in your XAML to false or true, you will get the following exception at runtime.
System.InvalidOperationException: The BindableProperty "IsEnabled" is readonly.
And if you take a look at Microsoft's documentation, you will notice that you cannot directly set IsEnabled property of a toolbar item.
For disabling a toolbar item, the suggested way is to use a command and it's CanExecute.
I found out a way to solve this problem, at least a way better than implementing OnPropertyChange for btnTest
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="tlbSave" Text="Save" Clicked="Handle_Clicked" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout Padding="10" VerticalOptions="CenterAndExpand">
<Entry x:Name="txtTest" HorizontalOptions="FillAndExpand" />
<Button x:Name="btnTest" Text="HIDDEN">
<Button.Triggers>
<MultiTrigger TargetType="Button">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference txtTest}, Path=Text.Length,
Converter={convert:IsPositiveIntegerConverter}}" Value="true" />
</MultiTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiTrigger>
</Button.Triggers>
<Button.IsEnabled>
<Binding Source="{x:Reference tlbSave}" Path="IsEnabled" Mode="OneWayToSource" />
</Button.IsEnabled>
</Button>
</StackLayout>
</ContentPage.Content>
Then set btnTest.IsEnabled = false; inside constructor and everything will go as smooth as I want.

Picker with custom Items [Xaml]

I am trying to figure out a way how to create a picker with custom items in XAML. I am not sure if it is possible to achieve this task only using xaml. The picker would have to contain items that consist of a label and a switch. The code below illustrates the end goal:
<Picker Title="Picker title here">
<Picker.ItemsSource>
<StackLayout Orientation="Horizontal">
<Label Text="Hello Xamarin.Forms!" />
<Switch />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Hello Xamarin.Forms2!" />
<Switch />
</StackLayout>
</Picker.ItemsSource>
</Picker>
It's not possible. I think you can create a Popup with a ListView, where you have a ViewCell with all controls you need

Bound combobox: text disappearing after sorting the source list of strings

Ive got an ObservableCollection<string> list, which is bound to a combobox. This combobox is in a datatemplate which is inside a 'DataGridTemplateColumn'.
When the datagrid is displayed (with all the rows), the column displaying this combobox works just fine. The user can select the items in the combobox, and when it's selected, the string is bound to the cell. (Just for your info: the datagrid is bound to another ObservableCollection so the cell text gets updated in that list - but i don't think it's relevant to my problem).
This is all good but a problem arises when i go to 'add' another item in the ObservableCollection<string> list that the combo box is bound to, and perform a sort. The text disappears in the 'textbox' part of some of the previously modified comboboxes. If i do not sort the list, (just add a new value) everything is fine.
I think what is happenning is that the binding gets screwed up when i re-sort the list. Because the list has 'changed', the order of the strings in the list are now different, so the binding doesn't know what to display.
How can i get this to work? The previously selected comboboxes's text disappears when i re-sort the ObservableCollection<string> list.
My <DataGridTemplateColumn> containing the combo box is:
<WpfToolkit:DataGridTemplateColumn
Header="Category" Width="1*"
CellTemplate="{StaticResource ComboBoxCellDataTemplate}"
CellEditingTemplate="{StaticResource ComboBoxCellEditingTemplate}"/>
...and the related DataTemplates are:
<DataTemplate x:Key="ComboBoxCellDataTemplate">
<Label x:Name="lblCombo" Content="{Binding Category}" Style="{StaticResource BaseLabelCellStyle}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Categories, Mode=TwoWay}" Value="Both">
<Setter TargetName="lblCombo" Property="IsEnabled" Value="False" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate x:Key="ComboBoxCellEditingTemplate">
<!-- min=60, max=600 also, add in a 'specific' scalar value -->
<ComboBox
x:Name="comboBox"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Categories, Mode=TwoWay}"
SelectedItem="{Binding Category}" LostFocus="comboBox_LostFocus" IsEditable="True" PreviewKeyDown="comboBox_PreviewKeyDown" MaxDropDownHeight="100" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Enabled}" Value="False">
<Setter TargetName="comboBox" Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Categories, Mode=TwoWay}" Value="Both">
<Setter TargetName="comboBox" Property="IsEnabled" Value="True" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Note that the majority of this code is by Samuel Moura at http://sweux.com/blogs/smoura/index.php/tag/datagridcolumn/
Hey I think I have a solution for you. Just add the following line to your Datagrid definition
SelectionUnit="Cell"
I dunno how, it worked for me:) Just give it a try and let me know if it helps.

Resources