Last active
February 15, 2025 05:09
-
-
Save gpproton/181a9263721be1dc6625ae44e1eccc19 to your computer and use it in GitHub Desktop.
A basic dotnet MAUI sample segment control example using BindableLayout
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- Working code --> | |
<?xml version="1.0" encoding="utf-8" ?> | |
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | |
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |
x:Class="XClaim.Mobile.Views.Segment" | |
x:Name="this"> | |
<Border Padding="3" StrokeThickness="0" BackgroundColor="{DynamicResource Tertiary}"> | |
<Border.StrokeShape> | |
<RoundRectangle> | |
<RoundRectangle.CornerRadius> | |
<CornerRadius>10</CornerRadius> | |
</RoundRectangle.CornerRadius> | |
</RoundRectangle> | |
</Border.StrokeShape> | |
<ScrollView> | |
<FlexLayout BindableLayout.ItemsSource="{Binding Source={x:Reference this},Path=SegmentItems}" RadioButtonGroup.SelectedValue="{Binding Source={x:Reference this},Path=SelectedItem}" MinimumHeightRequest="40" Wrap="NoWrap" JustifyContent="SpaceBetween" RadioButtonGroup.GroupName="SegmentRadios"> | |
<BindableLayout.ItemTemplate> | |
<DataTemplate x:DataType="{x:Type x:String}"> | |
<RadioButton FlexLayout.Basis="50%" Content="{Binding .}" Value="{Binding .}"> | |
<RadioButton.ControlTemplate> | |
<ControlTemplate> | |
<Grid VerticalOptions="Center"> | |
<VisualStateManager.VisualStateGroups> | |
<VisualStateGroupList> | |
<VisualStateGroup x:Name="CheckedStates"> | |
<VisualState x:Name="Checked"> | |
<VisualState.Setters> | |
<Setter TargetName="SegmentItem" Property="Button.TextColor" Value="{DynamicResource White}" /> | |
<Setter TargetName="SegmentItem" Property="Button.BackgroundColor" Value="{DynamicResource Primary}" /> | |
</VisualState.Setters> | |
</VisualState> | |
<VisualState x:Name="Unchecked"> | |
<VisualState.Setters> | |
<Setter TargetName="SegmentItem" Property="Button.TextColor" Value="{DynamicResource Primary}" /> | |
<Setter TargetName="SegmentItem" Property="Button.BackgroundColor" Value="Transparent" /> | |
</VisualState.Setters> | |
</VisualState> | |
</VisualStateGroup> | |
</VisualStateGroupList> | |
</VisualStateManager.VisualStateGroups> | |
<Button x:Name="SegmentItem" Clicked="OnItemClicked" HorizontalOptions="Fill" Text="{TemplateBinding Content}" /> | |
</Grid> | |
</ControlTemplate> | |
</RadioButton.ControlTemplate> | |
</RadioButton> | |
</DataTemplate> | |
</BindableLayout.ItemTemplate> | |
</FlexLayout> | |
</ScrollView> | |
</Border> | |
</ContentView> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Working code | |
// Maui.BindableProperty.Generator for clean bindable properties | |
#pragma warning disable | |
#nullable enable | |
namespace XClaim.Mobile.Views; | |
public partial class Segment : ContentView | |
{ | |
[AutoBindable] | |
private readonly string[]? _segmentItems; | |
[AutoBindable] | |
private readonly string? _selectedItem; | |
public enum ItemState { Pending, Confirmed, Completed } | |
public Segment() { | |
InitializeComponent(); | |
if(SegmentItems is null) SegmentItems = Enum.GetNames(typeof(ItemState)); | |
if(SegmentItems is not null) SelectedItem = SegmentItems[0]; | |
} | |
async void OnItemClicked(object sender, EventArgs args) { | |
SelectedItem = (sender as Button).Text; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Not working - Unable to bind VisualStateGroup | |
// Still trying to implement this with only code | |
public class SegmentCode : Border { | |
readonly string[] items = { "Pending", "Confirmed", "Completed" }; | |
// Extending is not equivalent to X:Name, looking for a solution | |
class SegmentButton : Button { | |
public SegmentButton() => this.Margins(0, 0, 8, 0); | |
} | |
public SegmentCode() { | |
Padding = 3; | |
Margin = 8; | |
StrokeShape = new RoundRectangle { | |
CornerRadius = new CornerRadius(10) | |
}; | |
SetDynamicResource(BackgroundColorProperty, "Tertiary"); | |
var layout = new HorizontalStackLayout() | |
.ItemsSource(items) | |
.ItemTemplate(new DataTemplate(() => new RadioButton { | |
ControlTemplate = new ControlTemplate(() => new SegmentButton() | |
.Bind(Button.TextProperty, "Content", source: RelativeBindingSource.TemplatedParent)) | |
}.Bind(RadioButton.ContentProperty))); | |
RadioButtonGroup.SetGroupName(layout, "SegmentRadios"); | |
// Todo: Add VisualStateGroup to the baindable layout | |
// Todo: Properly name child crontrols to reference in VistualState | |
var vsGroups = new VisualStateGroup() { | |
Name = "CheckedStates", | |
}; | |
vsGroups.States.Add(new VisualState { | |
Name = "Checked", | |
Setters = { | |
new Setter { TargetName = nameof(SegmentButton), Property = Button.BackgroundColorProperty, Value = Colors.Indigo } | |
} | |
}); | |
vsGroups.States.Add(new VisualState { | |
Name = "Unchecked", | |
Setters = { | |
new Setter { TargetName = nameof(SegmentButton), Property = Button.BackgroundColorProperty, Value = Colors.Transparent }, | |
new Setter { TargetName = nameof(SegmentButton), Property = Button.TextColorProperty, Value = Colors.Indigo } | |
} | |
}); | |
var vsList = new VisualStateGroupList(); | |
vsList.Add(vsGroups) | |
VisualStateManager.SetVisualStateGroups(layout, vsGroups); | |
Content = layout; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My real goal is to properly implement this control in C# Markup, and i've been hit a lot of roadblock as there's not enough information on using VisualStateGroupList and BindableLayout together with C# Markup, so any help be appreciated.