Skip to content

Commit

Permalink
Merge pull request #713 from enisn/dropdownfield
Browse files Browse the repository at this point in the history
Introduce DropdownField
  • Loading branch information
enisn authored Jul 14, 2024
2 parents 0106136 + 422ebb8 commit 27aa247
Show file tree
Hide file tree
Showing 11 changed files with 369 additions and 52 deletions.
4 changes: 4 additions & 0 deletions demo/UraniumApp/AppShell.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@
<ShellContent ContentTemplate="{DataTemplate inputFields:PickerFieldPage}" Icon="{FontImageSource Glyph={x:Static m:MaterialOutlined.Arrow_circle_down}, FontFamily=MaterialOutlined, Color={AppThemeBinding {StaticResource Primary}, Dark={StaticResource PrimaryDark}}}"/>
</FlyoutItem>

<FlyoutItem Title="DropdownField" Icon="{FontImageSource Glyph={x:Static m:MaterialOutlined.Dropdown}, FontFamily=MaterialOutlined, Color={AppThemeBinding {StaticResource Primary}, Dark={StaticResource PrimaryDark}}}">
<ShellContent ContentTemplate="{DataTemplate pages:DropdownFieldPage}" Icon="{FontImageSource Glyph={x:Static m:MaterialOutlined.Dropdown}, FontFamily=MaterialOutlined, Color={AppThemeBinding {StaticResource Primary}, Dark={StaticResource PrimaryDark}}}"/>
</FlyoutItem>

<FlyoutItem Title="MultiplePickerField" Icon="{FontImageSource Glyph={x:Static m:MaterialOutlined.Arrow_circle_down}, FontFamily=MaterialOutlined, Color={AppThemeBinding {StaticResource Primary}, Dark={StaticResource PrimaryDark}}}">
<ShellContent ContentTemplate="{DataTemplate inputFields:MultiplePickerFieldPage}" Icon="{FontImageSource Glyph={x:Static m:MaterialOutlined.Grid_view}, FontFamily=MaterialOutlined, Color={AppThemeBinding {StaticResource Primary}, Dark={StaticResource PrimaryDark}}}"/>
</FlyoutItem>
Expand Down
18 changes: 2 additions & 16 deletions demo/UraniumApp/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<Label Text="Hello, Uranium! ☢️" FontSize="Large" />
<Label Text="Welcome to the demo app." />
</StackLayout>

<Grid ColumnDefinitions="Auto,*">
<Image Rotation="-45" Margin="15">
<Image.Source>
Expand All @@ -23,21 +23,7 @@
<Label FontSize="Large" Grid.Column="1" Text="Use the side navigation drawer to navigate to the other pages." VerticalOptions="Center"/>
</Grid>

<uranium:SelectableLabel Margin="15" Text="Hello, World! This text should be selectable!" />

<Label Text="{Binding SelectedItem, Source={x:Reference dropdown}}" />
<BoxView StyleClass="Divider" />
<uranium:SelectableLabel Margin="15" Text="Hello, World! This text should be selectable!" />

<uranium:Dropdown BackgroundColor="Transparent" Margin="20" x:Name="dropdown">
<uranium:Dropdown.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>

</x:Array>
</uranium:Dropdown.ItemsSource>
</uranium:Dropdown>

</VerticalStackLayout>
</ContentPage>
90 changes: 90 additions & 0 deletions demo/UraniumApp/Pages/DropdownFieldPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:UraniumApp"
xmlns:uranium="http://schemas.enisn-projects.io/dotnet/maui/uraniumui"
xmlns:material="http://schemas.enisn-projects.io/dotnet/maui/uraniumui/material"
x:Class="UraniumApp.Pages.DropdownFieldPage"
Title="DropdownFieldPage">

<ContentPage.Resources>
<x:String x:Key="DocLink">https://enisn-projects.io/docs/en/uranium/2.9/infrastructure/Dropdown</x:String>
<x:String x:Key="SourceLink">https://github.com/enisn/UraniumUI/blob/develop/demo/UraniumApp/Pages/DropdownFieldPage.xaml</x:String>
</ContentPage.Resources>

<Grid RowDefinitions="*">
<material:TabView TabPlacement="Top">
<material:TabItem Title="DropdownField">

<ScrollView>
<VerticalStackLayout Padding="20">
<Label Text="DropdownField" FontSize="Title" />
<Label Text="UraniumUI.Material.Controls" FontSize="Micro" Opacity=".6" />

<HorizontalStackLayout Padding="0,20">
<Button Text="Documentation" Command="{x:Static uranium:Commands.OpenLinkCommand}" CommandParameter="{StaticResource DocLink}" StyleClass="OutlinedButton" ImageSource="{FontImageSource Glyph={x:Static uranium:MaterialSharp.File_open}, FontFamily=MaterialSharp, Color={AppThemeBinding {StaticResource OnBackground}, Dark={StaticResource OnBackgroundDark}}}" />
<Button Text="Source" StyleClass="OutlinedButton" Command="{x:Static uranium:Commands.OpenLinkCommand}" CommandParameter="{StaticResource SourceLink}" ImageSource="{FontImageSource Glyph={x:Static uranium:MaterialSharp.Code}, FontFamily=MaterialSharp, Color={AppThemeBinding {StaticResource OnBackground}, Dark={StaticResource OnBackgroundDark}}}" />
</HorizontalStackLayout>

<StackLayout HorizontalOptions="Start">

<material:DropdownField Title="Choose" AllowClear="True" StyleClass="ControlPreview">
<material:DropdownField.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Option 1</x:String>
<x:String>Option 2</x:String>
<x:String>Option 3</x:String>
</x:Array>
</material:DropdownField.ItemsSource>
</material:DropdownField>
</StackLayout>

<BoxView StyleClass="Divider"/>

<!--<local:ViewShowcaseView>
<material:DropdownField x:Name="demoDropdownField" />
<local:ViewShowcaseView.SidePanel>
<VerticalStackLayout>
<local:PropertyEditorView
MaximumHeightRequest="600"
HierarchyLimitType="{Type material:InputField}"
Hierarchical="True"
Value="{x:Reference demoDropdownField}"
/>
</VerticalStackLayout>
</local:ViewShowcaseView.SidePanel>
</local:ViewShowcaseView>-->


</VerticalStackLayout>
</ScrollView>

</material:TabItem>
<material:TabItem Title="Dropdown">
<VerticalStackLayout Padding="20">
<Label Text="Dropdown" FontSize="Title" />
<Label Text="UraniumUI.Controls" FontSize="Micro" Opacity=".6" />

<VerticalStackLayout StyleClass="ControlPreview" HorizontalOptions="Center" Spacing="32">

<uranium:Dropdown Placeholder="Choose" x:Name="dropdown">
<uranium:Dropdown.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
</x:Array>
</uranium:Dropdown.ItemsSource>
</uranium:Dropdown>

<Button StyleClass="TextButton" Text="Clear" Clicked="Button_Clicked" />
</VerticalStackLayout>
</VerticalStackLayout>
</material:TabItem>
</material:TabView>

</Grid>
</ContentPage>
14 changes: 14 additions & 0 deletions demo/UraniumApp/Pages/DropdownFieldPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace UraniumApp.Pages;

public partial class DropdownFieldPage : ContentPage
{
public DropdownFieldPage()
{
InitializeComponent();
}

private void Button_Clicked(object sender, EventArgs e)
{
dropdown.SelectedItem = null;
}
}
169 changes: 167 additions & 2 deletions src/UraniumUI.Material/Controls/DropdownField.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
using UraniumUI.Controls;
using System.Collections;
using System.Windows.Input;
using UraniumUI.Controls;
using UraniumUI.Pages;
using UraniumUI.Resources;
using UraniumUI.Views;
using Path = Microsoft.Maui.Controls.Shapes.Path;

namespace UraniumUI.Material.Controls;
public class DropdownField : InputField
Expand All @@ -8,11 +14,170 @@ public class DropdownField : InputField
public override View Content { get; set; } = new Dropdown
{
VerticalOptions = LayoutOptions.Center,
Margin = new Thickness(15, 0),
#if WINDOWS
Margin = new Thickness(5, 0, 0, 0),
#endif
HorizontalOptions = LayoutOptions.Fill,
StyleClass = new List<string> { "InputField.Dropdown" }
};

protected StatefulContentView iconClear = new StatefulContentView
{
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.End,
IsVisible = false,
Padding = 10,
Content = new Path
{
Data = UraniumShapes.X,
Fill = ColorResource.GetColor("OnBackground", "OnBackgroundDark", Colors.DarkGray).WithAlpha(.5f),
}
};

public override bool HasValue => SelectedItem != null;

public event EventHandler<object> SelectedItemChanged;

public DropdownField()
{
iconClear.TappedCommand = new Command(OnClearTapped);
UpdateClearIconState();

DropdownView.SetBinding(Dropdown.SelectedItemProperty, new Binding(nameof(SelectedItem), BindingMode.TwoWay, source: this));
DropdownView.SetBinding(Dropdown.ItemsSourceProperty, new Binding(nameof(ItemsSource), source: this));
DropdownView.SetBinding(Dropdown.IsEnabledProperty, new Binding(nameof(IsEnabled), source: this));
}

protected override object GetValueForValidator()
{
return SelectedItem;
}

public override void ResetValidation()
{
SelectedItem = null;
base.ResetValidation();
}

protected virtual void OnClearTapped(object parameter)
{
if (IsEnabled)
{
SelectedItem = null;
DropdownView.Unfocus();
}
}

protected virtual void UpdateClearIconState()
{
if (AllowClear)
{
if (!endIconsContainer.Contains(iconClear))
{
endIconsContainer.Add(iconClear);
}
}
else
{
endIconsContainer.Remove(iconClear);
}
}

protected virtual void OnSelectedItemChanged()
{
OnPropertyChanged(nameof(SelectedItem));
CheckAndShowValidations();

if (AllowClear)
{
iconClear.IsVisible = SelectedItem != null;
}

UpdateState();
SelectedItemChanged?.Invoke(this, SelectedItem);
SelectedItemChangedCommand?.Execute(SelectedItem);
}

protected virtual void OnAllowClearChanged()
{
UpdateClearIconState();
}

#region BindableProperties

public IList ItemsSource { get => (IList)GetValue(ItemsSourceProperty); set => SetValue(ItemsSourceProperty, value); }

public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
nameof(ItemsSource),
typeof(IEnumerable),
typeof(DropdownField),
propertyChanged: (bindable, oldValue, newValue) => (bindable as DropdownField).DropdownView.ItemsSource = (IList)newValue);

public object SelectedItem { get => GetValue(SelectedItemProperty); set => SetValue(SelectedItemProperty, value); }

public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create(
nameof(SelectedItem),
typeof(object),
typeof(DropdownField),
propertyChanged: (bindable, oldValue, newValue) => (bindable as DropdownField).OnSelectedItemChanged());

public bool AllowClear { get => (bool)GetValue(AllowClearProperty); set => SetValue(AllowClearProperty, value); }

public static readonly BindableProperty AllowClearProperty = BindableProperty.Create(
nameof(AllowClear),
typeof(bool),
typeof(DropdownField),
defaultValue: false,
propertyChanged: (bindable, oldValue, newValue) => (bindable as DropdownField).OnAllowClearChanged());

public ICommand SelectedItemChangedCommand { get => (ICommand)GetValue(SelectedItemChangedCommandProperty); set => SetValue(SelectedItemChangedCommandProperty, value); }

public static readonly BindableProperty SelectedItemChangedCommandProperty = BindableProperty.Create(
nameof(SelectedItemChangedCommand),
typeof(ICommand),
typeof(DropdownField));

public Color TextColor { get => (Color)GetValue(TextColorProperty); set => SetValue(TextColorProperty, value); }

public static readonly BindableProperty TextColorProperty = BindableProperty.Create(
nameof(TextColor),
typeof(Color),
typeof(DropdownField),
defaultValue: Dropdown.TextColorProperty.DefaultValue,
propertyChanged: (bindable, oldValue, newValue) => (bindable as DropdownField).DropdownView.TextColor = (Color)newValue);

public string FontFamily { get => (string)GetValue(FontFamilyProperty); set => SetValue(FontFamilyProperty, value); }

public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create(
nameof(FontFamily),
typeof(string),
typeof(DropdownField),
defaultValue: Dropdown.FontFamilyProperty.DefaultValue,
propertyChanged: (bindable, oldValue, newValue) => (bindable as DropdownField).DropdownView.FontFamily = (string)newValue);

public double FontSize { get => (double)GetValue(FontSizeProperty); set => SetValue(FontSizeProperty, value); }
public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(
nameof(FontSize),
typeof(double),
typeof(DropdownField),
defaultValue: Dropdown.FontSizeProperty.DefaultValue,
propertyChanged: (bindable, oldValue, newValue) => (bindable as DropdownField).DropdownView.FontSize = (double)newValue);

public FontAttributes FontAttributes { get => (FontAttributes)GetValue(FontAttributesProperty); set => SetValue(FontAttributesProperty, value); }
public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create(
nameof(FontAttributes),
typeof(FontAttributes),
typeof(DropdownField),
defaultValue: Dropdown.FontAttributesProperty.DefaultValue,
propertyChanged: (bindable, oldValue, newValue) => (bindable as DropdownField).DropdownView.FontAttributes = (FontAttributes)newValue);

public TextAlignment HorizontalTextAlignment { get => (TextAlignment)GetValue(HorizontalTextAlignmentProperty); set => SetValue(HorizontalTextAlignmentProperty, value); }

public static readonly BindableProperty HorizontalTextAlignmentProperty = BindableProperty.Create(
nameof(HorizontalTextAlignment),
typeof(TextAlignment),
typeof(DropdownField),
defaultValue: Dropdown.HorizontalTextAlignmentProperty.DefaultValue,
propertyChanged: (bindable, oldValue, newValue) => (bindable as DropdownField).DropdownView.HorizontalTextAlignment = (TextAlignment)newValue);
#endregion
}
4 changes: 1 addition & 3 deletions src/UraniumUI.Material/Controls/InputField.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using Microsoft.Maui.Controls.Shapes;
using UraniumUI.Resources;
using UraniumUI.Extensions;
using System.Collections;
using Microsoft.Maui.Controls;
using UraniumUI.Resources;

namespace UraniumUI.Material.Controls;

Expand Down
6 changes: 0 additions & 6 deletions src/UraniumUI/Controls/Dropdown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,6 @@ protected virtual void OnItemsSourceChanged(IList oldValue, IList newValue)
{
newObservable.CollectionChanged += ItemsSource_CollectionChanged;
}

if (SelectedItem is null && ItemsSource.Count > 0)
{
SelectedItem = ItemsSource[0];
Text = SelectedItem.ToString();
}
}

private void ItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
Expand Down
Loading

0 comments on commit 27aa247

Please sign in to comment.