Customize look of selected element - xamarin.forms

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:

Related

Xamarin CollectionView event and command issue

I work on the front end of our app, configuring the UI. Our app originally had a ListView using Xamarin Community Toolkit's EventToCommandBehavior with custom ViewCells to facilitate the search. We set up custom renderers to change the ViewCell's background color. However, when I moved over to the Mac, we discovered that none of that worked with iOS; the cell background would not change.
At this point, I switched to a CollectionView with a TapGestureRecognizer on the grid using VisualStateManager to change the background color. Since then, I can either get the grid selection to highlight without the command enabling our buttons or the command to fire which enables the buttons, but the grid selection will not highlight. Simply put, I either get the command or the event but have been unable to get them working together. This is also a problem on our store page; the IAP's never highlighted before the purchase confirmation popped up. We have been experiencing this issue from the start and never noticed.
Here is the relevant XAML:
<!--Faction Search Results-->
<Frame Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="6" BackgroundColor="Black" BorderColor="White" CornerRadius="5">
<CollectionView ItemsSource="{Binding FactionItems}"
BackgroundColor="Transparent">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid x:DataType="Data:Faction" BackgroundColor="Black">
<Grid.GestureRecognizers>
<TapGestureRecognizer
NumberOfTapsRequired="1"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:FactionTopPageViewModel}}, Path=ItemTapped}"
CommandParameter="{Binding .}">
</TapGestureRecognizer>
</Grid.GestureRecognizers>
<Grid.RowDefinitions>
<RowDefinition Height="{markups:OnScreenSize DefaultSize='12', iPod='20', iPhoneSE='20', iPhoneXR='20', iPhoneX='20', iPhone13='25', iPhone7p='25', iPhone11pm='25', iPhone13pm='16',
iPadMini='35', iPad9p7='35', iPad='35', iPadAir='35', iPad11='35', iPad12p9='40', Nexus1='20', NexusR='25', Nexus7R='30', Pixel2R='25', Pixel3R='25', GalaxyS8='25', Nexus6P='25', Pixel3XL='25', PixelC='40'}" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Padding="10,5" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4" Text="{Binding FactionName}" HorizontalOptions="Start" VerticalTextAlignment="End" FontAttributes="Bold"
FontSize="{markups:OnScreenSize DefaultSize='12', iPod='15', iPhoneSE='15', iPhoneXR='18', iPhoneX='19', iPhone13='19', iPhone7p='19', iPhone11pm='19', iPhone13pm='16',
iPadMini='30', iPad9p7='30', iPad='32', iPadAir='32', iPad11='34', iPad12p9='34', Nexus1='14', NexusR='14', Nexus7R='22', Pixel2R='20', Pixel3R='20', GalaxyS8='20', Nexus6P='18', Pixel3XL='18', PixelC='34'}" />
<Label Padding="0,5" Grid.Row="0" Grid.Column="4" Grid.ColumnSpan="2" Text="{Binding NumberMembersString}" HorizontalOptions="Center" VerticalTextAlignment="End" FontAttributes="Bold"
FontSize="{markups:OnScreenSize DefaultSize='12', iPod='15', iPhoneSE='15', iPhoneXR='18', iPhoneX='19', iPhone13='19', iPhone7p='19', iPhone11pm='19', iPhone13pm='16',
iPadMini='30', iPad9p7='30', iPad='32', iPadAir='32', iPad11='34', iPad12p9='34', Nexus1='14', NexusR='14', Nexus7R='22', Pixel2R='20', Pixel3R='20', GalaxyS8='20', Nexus6P='18', Pixel3XL='18', PixelC='34'}"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal"></VisualState>
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="#ae00ff"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Relevant code from the ViewModel:
public Command<Faction> ItemTapped { get; }
public FactionTopPageViewModel()
{
ItemTapped = new Command<Faction>(OnItemSelected);
}
private void OnItemSelected(Faction faction)
{
if (faction == null)
{
SelectedItem = null;
DisableFactionButtons();
return;
}
EnableFactionButtons();
SelectedItem = faction;
}
This results in our buttons enabled at the bottom of the page, but the faction (essentially a team) is not being highlighted in the CollectionView, so the user does not receive confirmation of selecting the proper faction.
If I remove the tapgesture and work through the CollectionView commands setting the SelectionMode="Single", SelectionChangedCommand={Binding IsTapped}, and SelectionChangedCommandParameter={Binding .} then the selected Faction highlights without enabling any buttons. These issues are not platform-specific, like the ListView ViewCell background.
I have been working on this longer than I care to mention, as it seems like I have not wrapped my head around some relatively simple concept. Any help would be greatly appreciated, this issue is holding up the next release of our app.

Xamarin: Hide the button if condition is false

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.

How to write the Style for check box place in the GridCell UWP?

enter image description here
I have tried to write the style for check box placed in the Grid cell by setting the target type as checkbox, but its apply the style also for the filter checkbox. could anybody suggest me to write the style only for the Grid cell check box.
Please find the image attached above i have write a style only for the checkbox loaded in the grid cell instead of the applying to all
I tried it by this way
<Page.Resources>
<Style TargetType="CheckBox">
<Setter Property="Background" Value="Red"/>
</Style>
</Page.Resources>
<Page.DataContext>
<local:ViewModel/>
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<my:SfDataGrid ItemsSource="{Binding Orders}" AllowFiltering="True" />
</Grid>
You have to use Column property of DataGridCell and check its DisplayIndex value and write a DataTrigger.
Sample approach :
<DataGrid ...>
<DataGrid.Resources>
<Style TargetType="CheckBox">
<Setter Property="Background" Value="Green"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Column.DisplayIndex, RelativeSource={RelativeSource AncestorType=DataGridCell, Mode=FindAncestor}}" Value="0">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
Ok. #BalamuruganR I've made a simple code sample for you. Using the GridTemplateColumn and specify a "x:Key" for your custom style. Please check the following code sample:
<Page.Resources>
<Style x:Key="CheckBoxStyle1" TargetType="CheckBox">
<Setter Property="Background" Value="Red" />
</Style>
<DataTemplate x:Key="cellTemplate">
<CheckBox Content="DataGrid" IsChecked="{Binding Flag}" Style="{StaticResource CheckBoxStyle1}"></CheckBox>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<syncfusion:SfDataGrid x:Name="sfGrid" Grid.Column="0"
AllowGrouping="True"
AutoExpandGroups="True"
ShowGroupDropArea="True"
AllowEditing="True"
AllowFiltering="True"
AutoGenerateColumns="False"
ItemsSource="{Binding UserDetails}">
<syncfusion:SfDataGrid.Columns>
<syncfusion:GridTextColumn MappingName="UserId" />
<syncfusion:GridTextColumn MappingName="Name" />
<syncfusion:GridDateTimeColumn MappingName="DateofBirth" />
<syncfusion:GridNumericColumn MappingName="ContactNo" />
<syncfusion:GridTemplateColumn MappingName="Flag" CellTemplate="{StaticResource cellTemplate}" />
</syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>
</Grid>

How to bind ToggleButtons to Enum values on ItemsControl?

I want to create a row of ToggleButtons for Enum values. The buttons must show current value of a property of MyEnumType (by their state) and change the property's value when pressed.
I've found a solution for binding a bunch of separate CheckBoxes to their corresponding enum values (one for each) here, but I'm trying to create the ToggleButtons by ItemsControl (from the Enum type's values) so I wont have to remember to add a ToggleButton every time I add another value to my enum type (and also for shorter XAML code that creates the buttons). The problem is that I can't bind a ConverterParameter. Is there a clean and proper way to do this? Or am I doing everything wrong?
Here is my code now:
<ItemsControl ItemsSource="{Binding Source={local:EnumValues {x:Type local:MyEnumType}}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton Content="{Binding Converter={StaticResource MyEnumToNiceStringConverter}}"
IsChecked="{Binding Source=mySourceObject, Path=SelectedMyEnumValue, Converter={StaticResource EnumBooleanConverter}, ConverterParameter={Binding}}">
</ToggleButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The local:EnumValues is a MarkupExtension that returns a list of values from given Enum type.
The EnumBooleanConverter is a value converter from the above link that returns true if the bound enum value is equal to its ConverterParameter and supports ConvertBack from bool to enum value.
SelectedMyEnumValue is the property that the buttons are to reflect and modify.
This is a repeating problem for me (that some property cannot be bound) so if you are about to give me a totally different approach for the ToggleButtons, please also write how to work around the problem of such binding. It doesn't have to be bound forever, I just need to set the value once (without a bunch of Style-and-Triggers kind of code in XAML). Maybe another Markup Extension can do this?
Thanks!
I have found out that my question is a duplicate of this one (I got confused by its title and missed it). Sorry for this. I'm attaching a solution for my specific case based on answers from that post (using ListBox instead of ItemsControl and binding IsChecked to IsSelected). The main trick here is the style for hiding the selected item's blue background.
<ListBox ItemsSource="{Binding Source={local:EnumValues {x:Type local:MyEnumType}}}"
SelectedItem="{Binding Source=mySourceObject, Path=SelectedMyEnumValue}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<ToggleButton Content="{Binding Converter={StaticResource MyEnumToNiceStringConverter}}"
IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}">
</ToggleButton>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Anyway, this only solves one of my 2 questions, so if you know how to make binding of such properties as the ConverterParameter possible, please leave an answer. Thanks.

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