search bar in shell behavior
So, I need to modify, my behavior on desktop
I have the shell, with the Seach bar
<Window
x:Class="METROWIND.Views.MainWindow"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Window.TitleBar>
<TitleBar
Title="METROWIND"
BackgroundColor="{x:AppThemeBinding Dark={x:StaticResource Black}, Light={x:StaticResource Primary}}"
HeightRequest="60">
<TitleBar.Content>
<Border>
<SearchBar/>
</Border>
</TitleBar.Content>
<TitleBar.TrailingContent>
<ImageButton
Background="Transparent"
BorderWidth="0"
HeightRequest="36"
WidthRequest="36">
<ImageButton.Source>
<FontImageSource
FontFamily="SegoeMDL2"
Glyph=""
Size="16" />
</ImageButton.Source>
</ImageButton>
</TitleBar.TrailingContent>
</TitleBar>
</Window.TitleBar>
public partial class App : Application
{
AppShell shell;
public App(AppShell appShell)
{
SyncfusionLicenseProvider.RegisterLicense(AppConstants.SYNCFUSION_KEY);
InitializeComponent();
shell = appShell;
}
protected override Window CreateWindow(IActivationState? activationState)
{
Window window = new MainWindow(shell);
return window;
}
everything works fantastic, but what I want to do for desktop, is to make my collection of turbines globally available for you to search in the shell to open a new window WITH THE DETAIL
Also, I have a cahrgeStationPage, that display a combo box with the turbines to search, and mke the map go to that pin
public partial class ChargingStationsMapPageViewModel(
HttpService service, DeviceLanguageService deviceLanguage, TurbinesService turbinesService) :
HomePageViewModel(service, deviceLanguage, turbinesService)
{
private Map? MapView;
[ObservableProperty]
bool isOptionsOpen;
[ObservableProperty]
bool isExpanded;
[RelayCommand]
private void Appearing(Map map)
{
MapView = map;
}
[RelayCommand]
void ItemSelected(Turbine Turbine)
{
var mapSpan = MapSpan.FromCenterAndRadius(Turbine.Location,
Distance.FromKilometers(0.4));
MapView!.MoveToRegion(mapSpan);
IsExpanded = false;
}
[RelayCommand]
void OpenMenu()
{
IsOptionsOpen = true;
}
[RelayCommand]
void ChangeMapType(int mapType)
{
MapView!.MapType = mapType switch
{
0 => MapType.Street,
1 => MapType.Satellite,
2 => MapType.Hybrid, // Example: Handle mapType 2
_ => throw new ArgumentOutOfRangeException(nameof(mapType), mapType, "Invalid map type"),
};
IsOptionsOpen = false;
}
}
}
<ContentPage
x:Class="METROWIND.Views.ChargingStationsMapPage"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:constant="clr-namespace:METROWIND.Constants"
xmlns:controls="clr-namespace:METROWIND.Controls"
xmlns:expander="clr-namespace:Syncfusion.Maui.Expander;assembly=Syncfusion.Maui.Expander"
xmlns:maps="clr-namespace:Microsoft.Maui.Controls.Maps;assembly=Microsoft.Maui.Controls.Maps"
xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:model="clr-namespace:METROWIND.Models"
xmlns:popup="clr-namespace:Syncfusion.Maui.Popup;assembly=Syncfusion.Maui.Popup"
xmlns:rex="clr-namespace:METROWIND.Resources"
xmlns:vm="clr-namespace:METROWIND.ViewModel"
x:Name="stationsMapPage"
x:DataType="vm:ChargingStationsMapPageViewModel">
<ContentPage.Behaviors>
<mct:EventToCommandBehavior
Command="{x:Binding AppearingCommand}"
CommandParameter="{x:Reference ChargingStationMap}"
EventName="Appearing" />
</ContentPage.Behaviors>
<Grid>
<Border Style="{x:StaticResource ChargeStationBorderStyle}">
<expander:SfExpander
AnimationDuration="200"
IsExpanded="{x:Binding IsExpanded}">
<expander:SfExpander.Header>
<Grid RowDefinitions="48">
<Label Style="{x:StaticResource ChooseStationLabelStyle}" />
</Grid>
</expander:SfExpander.Header>
<expander:SfExpander.Content>
<Grid
Padding="10,0,0,0"
RowDefinitions="Auto">
<CollectionView ItemsSource="{x:Binding Turbines}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:TurbinePin">
<Border Stroke="Transparent">
<HorizontalStackLayout Spacing="10">
<Label Style="{x:StaticResource ElectricBoltLabelStyle}" />
<Label
Style="{x:StaticResource AddressLabelStyle}"
Text="{x:Binding Turbine.Name}" />
</HorizontalStackLayout>
<Border.Behaviors>
<mct:TouchBehavior
DefaultBackgroundColor="White"
PressedBackgroundColor="CornflowerBlue" />
</Border.Behaviors>
<Border.GestureRecognizers>
<TapGestureRecognizer
Command="{x:Binding Source={x:Reference stationsMapPage},
Path=BindingContext.ItemSelectedCommand}"
CommandParameter="{x:Binding Turbine}" />
</Border.GestureRecognizers>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</expander:SfExpander.Content>
</expander:SfExpander>
</Border>
<maps:Map
x:Name="ChargingStationMap"
ItemsSource="{x:Binding Turbines}"
VerticalOptions="FillAndExpand">
<maps:Map.ItemTemplate>
<DataTemplate x:DataType="model:TurbinePin">
<controls:CustomMapPin
Address="{x:Binding Turbine.Address}"
Images="{x:Binding Turbine.ImagesURLs}"
Label="{x:Binding Turbine.Name}"
Location="{x:Binding Turbine.Location}"
MarkerClickedCommand="{x:Binding PinClickedCommand}"
MarkerClickedCommandParameter="{x:Binding Turbine}" />
</DataTemplate>
</maps:Map.ItemTemplate>
</maps:Map>
<Button
x:Name="mapLayers"
Command="{x:Binding OpenMenuCommand}"
Style="{x:StaticResource MapButtonStyle}">
<Button.ImageSource>
<FontImageSource
FontFamily="ma"
Glyph="{x:Static constant:MaterialFonts.Layers}" />
</Button.ImageSource>
</Button>
<popup:SfPopup
IsOpen="{x:Binding IsOptionsOpen}"
RelativeView="{x:Binding Source={x:Reference mapLayers}}"
Style="{x:StaticResource ChargeStationPopupStyle}">
<popup:SfPopup.PopupStyle>
<popup:PopupStyle CornerRadius="8" />
</popup:SfPopup.PopupStyle>
<popup:SfPopup.ContentTemplate>
<DataTemplate>
<VerticalStackLayout Spacing="10">
<controls:CustomImageButton
Caption="{x:Static rex:AppResource.Default}"
ClickCommand="{x:Binding ChangeMapTypeCommand}"
ImageName="default_layer.png"
Parameters="0" />
<controls:CustomImageButton
Caption="{x:Static rex:AppResource.Satelite}"
ClickCommand="{x:Binding ChangeMapTypeCommand}"
ImageName="satelite_layer.png"
Parameters="2" />
</VerticalStackLayout>
</DataTemplate>
</popup:SfPopup.ContentTemplate>
</popup:SfPopup>
</Grid>
</ContentPage>
On this particular page, the search box, should take care of this
How is working right now
I have a homePage
that grabs all the turbines from the service and put it in a collection view
protected readonly TurbinesService _turbinesService;
public ObservableCollection<TurbinePin> Turbines => _turbinesService.TurbinePins;
public HomePageViewModel(HttpService service, DeviceLanguageService deviceLanguage, TurbinesService turbinesService)
{
deviceLanguageService = deviceLanguage;
httpService = service;
LoadNews();
_turbinesService = turbinesService;
OnPinMarkerClickedCommand = new Command<object>(OnPinMarkerClicked);
_turbinesService.GetTurbinePinsForUI(OnPinMarkerClickedCommand);
}
public ObservableCollection<Article>? NewsList { get; set; } =
[];
async void LoadNews()
{
var language = deviceLanguageService.GetDeviceCultureInfo();
var newsUrl = AppConstants.GetNewsUrl(language.TwoLetterISOLanguageName);
NewsList!.Clear();
var newsObj = await httpService.GetAsync<News>(newsUrl);
foreach (var item in newsObj!.Articles!)
{
NewsList.Add(item);
}
}
[RelayCommand]
protected void ShowNewsDetail(Article article)
{
if (article != null)
{
Shell.Current.GoToAsync($"{nameof(ArticleDetailsPage)}",
true,
new Dictionary<string, object> {
{ "articleObj", article }
});
}
}
void OnPinMarkerClicked(object turbine)
{
if (turbine != null)
{
Shell.Current.GoToAsync($"{nameof(TurbineDetailPage)}",
true,
new Dictionary<string, object> {
{ "SelectedTurbine", turbine }
});
};
}
}
}
and in my turbines collection page, I inherit from this page, in order to get the turbines
public partial class TurbinesCollectionPageViewModel(HttpService service, DeviceLanguageService deviceLanguage,
TurbinesService turbinesService) : HomePageViewModel(service, deviceLanguage, turbinesService)
{
CollectionView? TurbinesCollection;
[ObservableProperty]
Turbine? turbine;
[RelayCommand]
void PageEnter(CollectionView collectionView)
{
if (collectionView != null)
{
TurbinesCollection = collectionView;
}
}
[RelayCommand]
async Task SelectedItemChange(SfComboBox combo)
{
if (combo.SelectedIndex < 0)
{
return;
}
var item = Turbines.ElementAt(combo.SelectedIndex);
TurbinesCollection?.ScrollTo(combo.SelectedIndex, -1, ScrollToPosition.Center);
var inputView = combo.Children[1] as Entry;
#if ANDROID || IOS
if (KeyboardExtensions.IsSoftKeyboardShowing(inputView!))
{
await Task.Delay(200);
await inputView!.HideKeyboardAsync(default);
}
#else
await Task.CompletedTask;
#endif
}
}
and for I have a search box that can use to search
<Grid
Padding="20"
RowDefinitions="Auto,*"
RowSpacing="-30">
<inputLayout:SfTextInputLayout Style="{x:StaticResource TurbineCollectionComboBoxStyle}">
<editors:SfComboBox
x:Name="combobox"
DisplayMemberPath="Turbine.Name"
ItemsSource="{x:Binding Turbines}"
Style="{x:DynamicResource TurbinesCollectionComboBoxStyle}">
<editors:SfComboBox.Behaviors>
<mct:EventToCommandBehavior
Command="{x:Binding SelectedItemChangeCommand}"
CommandParameter="{x:Binding Source={x:Reference combobox}}"
EventName="SelectionChanged" />
</editors:SfComboBox.Behaviors>
</editors:SfComboBox>
</inputLayout:SfTextInputLayout>
<CollectionView
x:Name="TurbineCollection"
Grid.Row="1"
ItemsSource="{x:Binding Turbines}"
SelectionMode="None"
Style="{x:StaticResource TurbineCollectionViewStyle}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:TurbinePin">
<Border BackgroundColor="#578D57">
<Border.StrokeShape>
<RoundRectangle CornerRadius="8" />
</Border.StrokeShape>
<VerticalStackLayout>
<Label
Style="{x:StaticResource TurbineDataLabelStyleStyle}"
Text="{x:Binding Turbine.Name}" />
<Label
Style="{x:StaticResource TurbineDataLabelStyleStyle}"
Text="{x:Binding Turbine.Address}" />
<Label
Style="{x:StaticResource C02LabelStyle}"
Text="{x:Binding Turbine.FinalCo2Removed,
StringFormat='{0:F5} kg CO₂'}" />
</VerticalStackLayout>
<Border.GestureRecognizers>
<TapGestureRecognizer
Command="{x:Binding OnPinMarkerClickedCommand,
Source={x:RelativeSource AncestorType={x:Type vm:TurbinesCollectionPageViewModel}}}"
CommandParameter="{x:Binding}" />
</Border.GestureRecognizers>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>