mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
New menu item implementation based directly on MenuItem/ToggleMenuFlyoutItem
This commit is contained in:
parent
11cd45c099
commit
e06dcc5155
42
MapUiTools/Avalonia/MapMenuItem.Avalonia.cs
Normal file
42
MapUiTools/Avalonia/MapMenuItem.Avalonia.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
public class MapMenuItem : MenuItem
|
||||
{
|
||||
public MapMenuItem()
|
||||
{
|
||||
Icon = new TextBlock
|
||||
{
|
||||
FontFamily = new("Segoe MDL2 Assets"),
|
||||
FontWeight = FontWeight.Black,
|
||||
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
|
||||
};
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => Header as string;
|
||||
set => Header = value;
|
||||
}
|
||||
|
||||
protected IEnumerable<MapMenuItem> ParentMenuItems => (Parent as ItemsControl)?.Items.OfType<MapMenuItem>();
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(MenuItem);
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
base.OnPropertyChanged(args);
|
||||
|
||||
if (args.Property == IsCheckedProperty)
|
||||
{
|
||||
((TextBlock)Icon).Text = (bool)args.NewValue ? "\uE73E" : ""; // CheckMark
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,81 +1,37 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Metadata;
|
||||
using Avalonia.Styling;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MapControl
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
public class ToggleMenuFlyoutItem : MenuItem
|
||||
public partial class MenuButton
|
||||
{
|
||||
internal static readonly FontFamily SymbolFont = new("Segoe MDL2 Assets");
|
||||
|
||||
private readonly TextBlock icon = new()
|
||||
{
|
||||
FontFamily = SymbolFont,
|
||||
FontWeight = FontWeight.Black,
|
||||
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
|
||||
};
|
||||
|
||||
public ToggleMenuFlyoutItem(string text, object item, EventHandler<RoutedEventArgs> click)
|
||||
{
|
||||
Icon = icon;
|
||||
Header = text;
|
||||
Tag = item;
|
||||
Click += click;
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(MenuItem);
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
base.OnPropertyChanged(args);
|
||||
|
||||
if (args.Property == IsCheckedProperty)
|
||||
{
|
||||
icon.Text = (bool)args.NewValue ? "\uE73E" : ""; // CheckMark
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MenuButton : Button
|
||||
{
|
||||
protected MenuButton(string icon)
|
||||
public MenuButton()
|
||||
{
|
||||
var style = new Style();
|
||||
style.Setters.Add(new Setter(TextBlock.FontFamilyProperty, ToggleMenuFlyoutItem.SymbolFont));
|
||||
style.Setters.Add(new Setter(TextBlock.FontFamilyProperty, new FontFamily("Segoe MDL2 Assets")));
|
||||
style.Setters.Add(new Setter(TextBlock.FontSizeProperty, 20d));
|
||||
style.Setters.Add(new Setter(PaddingProperty, new Thickness(8)));
|
||||
Styles.Add(style);
|
||||
|
||||
Content = icon;
|
||||
Flyout = new MenuFlyout();
|
||||
Loaded += async (s, e) => await Initialize();
|
||||
}
|
||||
|
||||
public string Icon
|
||||
{
|
||||
get => Content as string;
|
||||
set => Content = value;
|
||||
}
|
||||
|
||||
public MenuFlyout Menu => (MenuFlyout)Flyout;
|
||||
|
||||
[Content]
|
||||
public ItemCollection Items => Menu.Items;
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(Button);
|
||||
|
||||
protected MenuFlyout CreateMenu()
|
||||
{
|
||||
var menu = new MenuFlyout();
|
||||
Flyout = menu;
|
||||
return menu;
|
||||
}
|
||||
|
||||
protected IEnumerable<ToggleMenuFlyoutItem> GetMenuItems()
|
||||
{
|
||||
return ((MenuFlyout)Flyout).Items.OfType<ToggleMenuFlyoutItem>();
|
||||
}
|
||||
|
||||
protected static MenuItem CreateMenuItem(string text, object item, EventHandler<RoutedEventArgs> click)
|
||||
{
|
||||
return new ToggleMenuFlyoutItem(text, item, click);
|
||||
}
|
||||
|
||||
protected static Separator CreateSeparator()
|
||||
{
|
||||
return new Separator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
90
MapUiTools/Shared/MapLayerMenuItem.cs
Normal file
90
MapUiTools/Shared/MapLayerMenuItem.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
#if WPF
|
||||
using System.Windows;
|
||||
using System.Windows.Markup;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Markup;
|
||||
#elif WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
#else
|
||||
using Avalonia.Metadata;
|
||||
using FrameworkElement = Avalonia.Controls.Control;
|
||||
#endif
|
||||
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
#if WPF
|
||||
[ContentProperty(nameof(MapLayer))]
|
||||
#elif UWP || WINUI
|
||||
[ContentProperty(Name = nameof(MapLayer))]
|
||||
#endif
|
||||
public class MapLayerMenuItem : MapMenuItem
|
||||
{
|
||||
#if AVALONIA
|
||||
[Content]
|
||||
#endif
|
||||
public FrameworkElement MapLayer { get; set; }
|
||||
|
||||
public Func<Task<FrameworkElement>> MapLayerFactory { get; set; }
|
||||
|
||||
public MapLayerMenuItem()
|
||||
{
|
||||
Click += async (s, e) =>
|
||||
{
|
||||
if (DataContext is MapBase map)
|
||||
{
|
||||
await Execute(map);
|
||||
|
||||
foreach (var item in ParentMenuItems.OfType<MapLayerMenuItem>())
|
||||
{
|
||||
item.IsChecked = map.Children.Contains(item.MapLayer);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public virtual async Task Execute(MapBase map)
|
||||
{
|
||||
map.MapLayer = MapLayer ?? (MapLayer = await MapLayerFactory.Invoke());
|
||||
IsChecked = true;
|
||||
}
|
||||
}
|
||||
|
||||
public class MapOverlayMenuItem : MapLayerMenuItem
|
||||
{
|
||||
public override async Task Execute(MapBase map)
|
||||
{
|
||||
var layer = MapLayer ?? (MapLayer = await MapLayerFactory.Invoke());
|
||||
|
||||
if (map.Children.Contains(layer))
|
||||
{
|
||||
map.Children.Remove(layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = 1;
|
||||
|
||||
foreach (var itemLayer in ParentMenuItems?
|
||||
.OfType<MapOverlayMenuItem>()
|
||||
.Select(item => item.MapLayer)
|
||||
.Where(itemLayer => itemLayer != null))
|
||||
{
|
||||
if (itemLayer == layer)
|
||||
{
|
||||
map.Children.Insert(index, itemLayer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (map.Children.Contains(itemLayer))
|
||||
{
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
#if WPF
|
||||
using System.Windows;
|
||||
using System.Windows.Markup;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Markup;
|
||||
#elif WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
#elif AVALONIA
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Metadata;
|
||||
using DependencyProperty = Avalonia.AvaloniaProperty;
|
||||
using FrameworkElement = Avalonia.Controls.Control;
|
||||
#endif
|
||||
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
#if WPF
|
||||
[ContentProperty(nameof(Layer))]
|
||||
#elif UWP || WINUI
|
||||
[ContentProperty(Name = nameof(Layer))]
|
||||
#endif
|
||||
public class MapLayerItem
|
||||
{
|
||||
#if AVALONIA
|
||||
[Content]
|
||||
#endif
|
||||
public FrameworkElement Layer { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
|
||||
public Func<Task<FrameworkElement>> LayerFactory { get; set; }
|
||||
|
||||
public async Task<FrameworkElement> GetLayer() => Layer ?? (Layer = await LayerFactory?.Invoke());
|
||||
}
|
||||
|
||||
#if WPF
|
||||
[ContentProperty(nameof(MapLayers))]
|
||||
#elif UWP || WINUI
|
||||
[ContentProperty(Name = nameof(MapLayers))]
|
||||
#endif
|
||||
public class MapLayersMenuButton : MenuButton
|
||||
{
|
||||
private FrameworkElement selectedLayer;
|
||||
|
||||
public MapLayersMenuButton()
|
||||
: base("\uE81E")
|
||||
{
|
||||
((INotifyCollectionChanged)MapLayers).CollectionChanged += async (s, e) => await InitializeMenu();
|
||||
((INotifyCollectionChanged)MapOverlays).CollectionChanged += async (s, e) => await InitializeMenu();
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MapProperty =
|
||||
DependencyPropertyHelper.Register<MapLayersMenuButton, MapBase>(nameof(Map), null,
|
||||
async (button, oldValue, newValue) => await button.InitializeMenu());
|
||||
|
||||
public MapBase Map
|
||||
{
|
||||
get => (MapBase)GetValue(MapProperty);
|
||||
set => SetValue(MapProperty, value);
|
||||
}
|
||||
|
||||
#if AVALONIA
|
||||
[Content]
|
||||
#endif
|
||||
public Collection<MapLayerItem> MapLayers { get; } = new ObservableCollection<MapLayerItem>();
|
||||
|
||||
public Collection<MapLayerItem> MapOverlays { get; } = new ObservableCollection<MapLayerItem>();
|
||||
|
||||
private async Task InitializeMenu()
|
||||
{
|
||||
if (Map != null)
|
||||
{
|
||||
var menu = CreateMenu();
|
||||
|
||||
foreach (var item in MapLayers)
|
||||
{
|
||||
menu.Items.Add(CreateMenuItem(item.Text, item, MapLayerClicked));
|
||||
}
|
||||
|
||||
var initialLayer = MapLayers.Select(l => l.GetLayer()).FirstOrDefault();
|
||||
|
||||
if (MapOverlays.Count > 0)
|
||||
{
|
||||
if (initialLayer != null)
|
||||
{
|
||||
menu.Items.Add(CreateSeparator());
|
||||
}
|
||||
|
||||
foreach (var item in MapOverlays)
|
||||
{
|
||||
menu.Items.Add(CreateMenuItem(item.Text, item, MapOverlayClicked));
|
||||
}
|
||||
}
|
||||
|
||||
if (initialLayer != null)
|
||||
{
|
||||
SetMapLayer(await initialLayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void MapLayerClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = (FrameworkElement)sender;
|
||||
var mapLayerItem = (MapLayerItem)item.Tag;
|
||||
|
||||
SetMapLayer(await mapLayerItem.GetLayer());
|
||||
}
|
||||
|
||||
private async void MapOverlayClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = (FrameworkElement)sender;
|
||||
var mapLayerItem = (MapLayerItem)item.Tag;
|
||||
|
||||
ToggleMapOverlay(await mapLayerItem.GetLayer());
|
||||
}
|
||||
|
||||
private void SetMapLayer(FrameworkElement layer)
|
||||
{
|
||||
if (selectedLayer != layer)
|
||||
{
|
||||
selectedLayer = layer;
|
||||
Map.MapLayer = selectedLayer;
|
||||
}
|
||||
|
||||
UpdateCheckedStates();
|
||||
}
|
||||
|
||||
private void ToggleMapOverlay(FrameworkElement layer)
|
||||
{
|
||||
if (Map.Children.Contains(layer))
|
||||
{
|
||||
Map.Children.Remove(layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = 1;
|
||||
|
||||
foreach (var overlay in MapOverlays.Select(o => o.Layer).Where(o => o != null))
|
||||
{
|
||||
if (overlay == layer)
|
||||
{
|
||||
Map.Children.Insert(index, layer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Map.Children.Contains(overlay))
|
||||
{
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCheckedStates();
|
||||
}
|
||||
|
||||
private void UpdateCheckedStates()
|
||||
{
|
||||
foreach (var item in GetMenuItems())
|
||||
{
|
||||
item.IsChecked = Map.Children.Contains(((MapLayerItem)item.Tag).Layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
MapUiTools/Shared/MapProjectionMenuItem.cs
Normal file
64
MapUiTools/Shared/MapProjectionMenuItem.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
#if WPF
|
||||
using System.Windows.Markup;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml.Markup;
|
||||
#elif WINUI
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
#else
|
||||
using Avalonia.Metadata;
|
||||
#endif
|
||||
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
#if WPF
|
||||
[ContentProperty(nameof(MapProjection))]
|
||||
#elif UWP || WINUI
|
||||
[ContentProperty(Name = nameof(MapProjection))]
|
||||
#endif
|
||||
public class MapProjectionMenuItem : MapMenuItem
|
||||
{
|
||||
#if AVALONIA
|
||||
[Content]
|
||||
#endif
|
||||
public string MapProjection { get; set; }
|
||||
|
||||
public MapProjectionMenuItem()
|
||||
{
|
||||
Click += (s, e) =>
|
||||
{
|
||||
if (DataContext is MapBase map)
|
||||
{
|
||||
Execute(map);
|
||||
|
||||
foreach (var item in ParentMenuItems.OfType<MapProjectionMenuItem>())
|
||||
{
|
||||
item.IsChecked = map.MapProjection.CrsId == item.MapProjection;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void Execute(MapBase map)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
if (map.MapProjection.CrsId != MapProjection)
|
||||
{
|
||||
try
|
||||
{
|
||||
map.MapProjection = MapProjectionFactory.Instance.GetProjection(MapProjection);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"{nameof(MapProjectionFactory)}: {ex.Message}");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
IsChecked = success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
#if WPF
|
||||
using System.Windows;
|
||||
using System.Windows.Markup;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Markup;
|
||||
#elif WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
#elif AVALONIA
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Metadata;
|
||||
using DependencyProperty = Avalonia.AvaloniaProperty;
|
||||
using FrameworkElement = Avalonia.Controls.Control;
|
||||
#endif
|
||||
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
#if WPF
|
||||
[ContentProperty(nameof(Projection))]
|
||||
#elif UWP || WINUI
|
||||
[ContentProperty(Name = nameof(Projection))]
|
||||
#endif
|
||||
public class MapProjectionItem
|
||||
{
|
||||
#if AVALONIA
|
||||
[Content]
|
||||
#endif
|
||||
public string Projection { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
||||
#if WPF
|
||||
[ContentProperty(nameof(MapProjections))]
|
||||
#elif UWP || WINUI
|
||||
[ContentProperty(Name = nameof(MapProjections))]
|
||||
#endif
|
||||
public class MapProjectionsMenuButton : MenuButton
|
||||
{
|
||||
private string selectedProjection;
|
||||
|
||||
public MapProjectionsMenuButton()
|
||||
: base("\uE809")
|
||||
{
|
||||
((INotifyCollectionChanged)MapProjections).CollectionChanged += (s, e) => InitializeMenu();
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MapProperty =
|
||||
DependencyPropertyHelper.Register<MapProjectionsMenuButton, MapBase>(nameof(Map), null,
|
||||
(button, oldValue, newValue) => button.InitializeMenu());
|
||||
|
||||
public MapBase Map
|
||||
{
|
||||
get => (MapBase)GetValue(MapProperty);
|
||||
set => SetValue(MapProperty, value);
|
||||
}
|
||||
|
||||
#if AVALONIA
|
||||
[Content]
|
||||
#endif
|
||||
public Collection<MapProjectionItem> MapProjections { get; } = new ObservableCollection<MapProjectionItem>();
|
||||
|
||||
private void InitializeMenu()
|
||||
{
|
||||
if (Map != null)
|
||||
{
|
||||
var menu = CreateMenu();
|
||||
|
||||
foreach (var item in MapProjections)
|
||||
{
|
||||
menu.Items.Add(CreateMenuItem(item.Text, item.Projection, MapProjectionClicked));
|
||||
}
|
||||
|
||||
var initialProjection = MapProjections.Select(p => p.Projection).FirstOrDefault();
|
||||
|
||||
if (initialProjection != null)
|
||||
{
|
||||
SetMapProjection(initialProjection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MapProjectionClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = (FrameworkElement)sender;
|
||||
var projection = (string)item.Tag;
|
||||
|
||||
SetMapProjection(projection);
|
||||
}
|
||||
|
||||
private void SetMapProjection(string projection)
|
||||
{
|
||||
if (selectedProjection != projection)
|
||||
{
|
||||
try
|
||||
{
|
||||
Map.MapProjection = MapProjectionFactory.Instance.GetProjection(projection);
|
||||
selectedProjection = projection;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"{nameof(MapProjectionFactory)}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCheckedStates();
|
||||
}
|
||||
|
||||
private void UpdateCheckedStates()
|
||||
{
|
||||
foreach (var item in GetMenuItems())
|
||||
{
|
||||
item.IsChecked = selectedProjection == (string)item.Tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
MapUiTools/Shared/MenuButton.cs
Normal file
50
MapUiTools/Shared/MenuButton.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
using System.Threading.Tasks;
|
||||
#if WPF
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#elif WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
#else
|
||||
using Avalonia.Controls;
|
||||
using DependencyProperty = Avalonia.AvaloniaProperty;
|
||||
#endif
|
||||
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
public partial class MenuButton : Button
|
||||
{
|
||||
public static readonly DependencyProperty MapProperty =
|
||||
DependencyPropertyHelper.Register<MenuButton, MapBase>(nameof(Map), null,
|
||||
async (button, oldValue, newValue) => await button.Initialize());
|
||||
|
||||
public MapBase Map
|
||||
{
|
||||
get => (MapBase)GetValue(MapProperty);
|
||||
set => SetValue(MapProperty, value);
|
||||
}
|
||||
|
||||
private async Task Initialize()
|
||||
{
|
||||
if (Map != null)
|
||||
{
|
||||
DataContext = Map;
|
||||
|
||||
if (Items.Count > 0)
|
||||
{
|
||||
if (Items[0] is MapLayerMenuItem mapLayerItem)
|
||||
{
|
||||
await mapLayerItem.Execute(Map);
|
||||
}
|
||||
else if (Items[0] is MapProjectionMenuItem mapProjectionItem)
|
||||
{
|
||||
mapProjectionItem.Execute(Map);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,11 +40,17 @@
|
|||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Shared\MapLayersMenuButton.cs">
|
||||
<Link>MapLayersMenuButton.cs</Link>
|
||||
<Compile Include="..\Shared\MapLayerMenuItem.cs">
|
||||
<Link>MapLayerMenuItem.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MapProjectionsMenuButton.cs">
|
||||
<Link>MapProjectionsMenuButton.cs</Link>
|
||||
<Compile Include="..\Shared\MapProjectionMenuItem.cs">
|
||||
<Link>MapProjectionMenuItem.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MenuButton.cs">
|
||||
<Link>MenuButton.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\MapMenuItem.WinUI.cs">
|
||||
<Link>MapMenuItem.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\MenuButton.WinUI.cs">
|
||||
<Link>MenuButton.WinUI.cs</Link>
|
||||
|
|
|
|||
18
MapUiTools/WPF/MapMenuItem.WPF.cs
Normal file
18
MapUiTools/WPF/MapMenuItem.WPF.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
public class MapMenuItem : MenuItem
|
||||
{
|
||||
public string Text
|
||||
{
|
||||
get => Header as string;
|
||||
set => Header = value;
|
||||
}
|
||||
|
||||
protected IEnumerable<MapMenuItem> ParentMenuItems
|
||||
=> (Parent as ItemsControl)?.Items.OfType<MapMenuItem>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +1,33 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
public class MenuButton : Button
|
||||
[ContentProperty(nameof(Items))]
|
||||
public partial class MenuButton
|
||||
{
|
||||
static MenuButton()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(MenuButton), new FrameworkPropertyMetadata(typeof(MenuButton)));
|
||||
}
|
||||
|
||||
protected MenuButton(string icon)
|
||||
public MenuButton()
|
||||
{
|
||||
Content = icon;
|
||||
|
||||
ContextMenu = new ContextMenu();
|
||||
DataContextChanged += (s, e) => ContextMenu.DataContext = e.NewValue;
|
||||
Loaded += async (s, e) => await Initialize();
|
||||
Click += (s, e) => ContextMenu.IsOpen = true;
|
||||
}
|
||||
|
||||
protected ContextMenu CreateMenu()
|
||||
public string Icon
|
||||
{
|
||||
var menu = new ContextMenu();
|
||||
ContextMenu = menu;
|
||||
return menu;
|
||||
get => Content as string;
|
||||
set => Content = value;
|
||||
}
|
||||
|
||||
protected IEnumerable<MenuItem> GetMenuItems()
|
||||
{
|
||||
return ContextMenu.Items.OfType<MenuItem>();
|
||||
}
|
||||
public ContextMenu Menu => ContextMenu;
|
||||
|
||||
protected static MenuItem CreateMenuItem(string text, object item, RoutedEventHandler click)
|
||||
{
|
||||
var menuItem = new MenuItem { Header = text, Tag = item };
|
||||
menuItem.Click += click;
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
protected static Separator CreateSeparator()
|
||||
{
|
||||
return new Separator();
|
||||
}
|
||||
public ItemCollection Items => ContextMenu.Items;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
18
MapUiTools/WinUI/MapMenuItem.WinUI.cs
Normal file
18
MapUiTools/WinUI/MapMenuItem.WinUI.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if UWP
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
public class MapMenuItem : ToggleMenuFlyoutItem
|
||||
{
|
||||
protected IEnumerable<MapMenuItem> ParentMenuItems
|
||||
=> (VisualTreeHelper.GetParent(this) as Panel)?.Children.OfType<MapMenuItem>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +1,31 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Markup;
|
||||
#elif WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
#endif
|
||||
|
||||
namespace MapControl.UiTools
|
||||
{
|
||||
public class MenuButton : Button
|
||||
[ContentProperty(Name = nameof(Items))]
|
||||
public partial class MenuButton
|
||||
{
|
||||
protected MenuButton(string icon)
|
||||
public MenuButton()
|
||||
{
|
||||
Content = new FontIcon { Glyph = icon };
|
||||
Flyout = new MenuFlyout();
|
||||
Loaded += async (s, e) => await Initialize();
|
||||
}
|
||||
|
||||
protected MenuFlyout CreateMenu()
|
||||
public string Icon
|
||||
{
|
||||
var menu = new MenuFlyout();
|
||||
Flyout = menu;
|
||||
return menu;
|
||||
get => (Content as FontIcon)?.Glyph;
|
||||
set => Content = new FontIcon { Glyph = value };
|
||||
}
|
||||
|
||||
protected IEnumerable<ToggleMenuFlyoutItem> GetMenuItems()
|
||||
{
|
||||
return ((MenuFlyout)Flyout).Items.OfType<ToggleMenuFlyoutItem>();
|
||||
}
|
||||
public MenuFlyout Menu => (MenuFlyout)Flyout;
|
||||
|
||||
protected static ToggleMenuFlyoutItem CreateMenuItem(string text, object item, RoutedEventHandler click)
|
||||
{
|
||||
var menuItem = new ToggleMenuFlyoutItem { Text = text, Tag = item };
|
||||
menuItem.Click += click;
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
protected static MenuFlyoutSeparator CreateSeparator()
|
||||
{
|
||||
return new MenuFlyoutSeparator();
|
||||
}
|
||||
public IList<MenuFlyoutItemBase> Items => Menu.Items;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue