我如何捕获一个按/点击事件在shell flyouitem



所以我想做的是捕获弹出菜单项上的按/单击事件,以便我可以导致菜单项出现或消失。这与我在。net Maui数据库绑定到shell弹出项IsVisible属性的问题有关,该问题已愉快地解决了。

看起来FlyOutItem没有分配点击处理程序,不像MenuItem。我试着使用菜单项,但我不能让它工作(也许我做错了-见后面)

我想使用一种行为,但它的用法超出了我渺小的人类大脑。我看着使用处理程序,啊,我可怜的头。

既然点击/按下FlyoutItemtem会导致一些事情发生,我当然可以得到那个事件并添加我自己的代码。

下面是我使用的一些基本代码:

AppShell.xaml

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="TSDZ2Monitor.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:sys="clr-namespace:System;assembly=netstandard"

xmlns:local="clr-namespace:TSDZ2Monitor"
xmlns:pages="clr-namespace:TSDZ2Monitor.Pages"
xmlns:parameters="clr-namespace:TSDZ2Monitor.Pages.Parameters"
xmlns:assistlevels="clr-namespace:TSDZ2Monitor.Pages.Parameters.AssistLevels"
xmlns:graphvariables="clr-namespace:TSDZ2Monitor.Pages.Parameters.GraphVariables"

Shell.FlyoutBehavior="Flyout"
FlyoutHeaderBehavior="Default"
FlyoutVerticalScrollMode="Auto"
FlyoutBackgroundColor="{StaticResource FlyoutBackgroundColor}">
<Shell.BindingContext>
<local:ControlMenuViewModelM />
</Shell.BindingContext>
<Shell.FlyoutHeaderTemplate>
<DataTemplate>
<Grid BackgroundColor="{StaticResource FlyoutBackgroundColor}"
HeightRequest="200">
<Image 
HeightRequest="200"
Source="bicycle.svg"
Margin="10, 10, 10, 10"
Opacity="0.6" />
<Label Text="TSDZ2 Monitor"
TextColor="White"
FontAttributes="Bold" />
</Grid>
</DataTemplate>
</Shell.FlyoutHeaderTemplate>
<Shell.FlyoutFooterTemplate>
<DataTemplate>
<StackLayout>
<Label Text="TSDZ2"
TextColor="GhostWhite"
FontAttributes="Bold"
HorizontalOptions="Center" />
<Label Text="{Binding Source={x:Static sys:DateTime.Now}, StringFormat='{0:MMMM dd, yyyy}'}"
TextColor="GhostWhite"
HorizontalOptions="Center" />
</StackLayout>
</DataTemplate>
</Shell.FlyoutFooterTemplate>
<Shell.ItemTemplate>
<DataTemplate>
<Grid ColumnDefinitions="0.2*, 0.8*">
<Image Grid.Column="0" 
Source="{Binding FlyoutIcon}"
Margin="0, 20, 0, 10"
VerticalOptions="Center"
HeightRequest="30" />
<Label Grid.Column="1"
Text="{Binding Title}"
TextColor="Yellow"
FontSize="20"
FontAttributes="Bold"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
</Shell.ItemTemplate>

<ShellContent 
Title="Display"
Icon="speedometer.svg"
ContentTemplate="{DataTemplate pages:DisplayPage}" />

<ShellContent 
Title="Bluetooth"
Icon="bluetooth.svg"
IsVisible="{Binding ShowMainMenu}"
ContentTemplate="{DataTemplate pages:BluetoothPage}" />
<ShellContent 
Title="Tracks"
Icon="tracks.svg"
IsVisible="{Binding ShowMainMenu}"
ContentTemplate="{DataTemplate pages:TracksPage}" />
<ShellContent 
Title="Parameters"                         
Icon="parameters.svg"
IsVisible="{Binding ShowMainMenu}"
<-------this what I want to intercept
ContentTemplate="{DataTemplate pages:ParametersPage}" />
<ShellContent 
Title="Settings"
Icon="settings.svg"
IsVisible="{Binding ShowMainMenu}"
ContentTemplate="{DataTemplate pages:SettingsPage}" />
<ShellContent 
Title="About"
Icon="about.svg"
IsVisible="{Binding ShowMainMenu}"
ContentTemplate="{DataTemplate pages:AboutPage}" />


<ShellContent 
Title="Assist Level"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:AssistLevelPage}" />

<ShellContent 
Title="Assist Level Power"
IsVisible="{Binding ShowAssistLevels}"
ContentTemplate="{DataTemplate assistlevels:AssistLevelPowerPage}" />

<ShellContent
Title="Assist Level Torque"
IsVisible="{Binding ShowAssistLevels}"
ContentTemplate="{DataTemplate assistlevels:AssistLevelTorquePage}" />

<ShellContent 
Title="Assist LevelCadence"
IsVisible="{Binding ShowAssistLevels}"
ContentTemplate="{DataTemplate assistlevels:AssistLevelCadencePage}" />

<ShellContent 
Title="Assist LevelEMTB"
IsVisible="{Binding ShowAssistLevels}"
ContentTemplate="{DataTemplate assistlevels:AssistLevelEMTBPage}" />

<ShellContent 
Title="Battery"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:BatteryPage}" />
<ShellContent 
Title="Motor"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:MotorPage}" />
<ShellContent 
Title="Motor Temperature"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:MotorTemperaturePage}" />

<ShellContent 
Title="SoC"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:SoCPage}" />

<ShellContent 
Title="Startup Boost"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:StartupBoostPage}" />

<ShellContent 
Title="Street Mode"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:StreetModePage}" />

<ShellContent 
Title="Technical"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:TechnicalPage}" />

<ShellContent 
Title="Torque Sensor"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:TorqueSensorPage}" />

<ShellContent 
Title="Trip Memories"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:TripMemoriesPage}" />

<ShellContent 
Title="Various"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:VariousPage}" />

<ShellContent 
Title="Wheel"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:WheelPage}" />

<ShellContent 
Title="Graph Variables"
IsVisible="{Binding ShowParameters}"
ContentTemplate="{DataTemplate parameters:GraphVariablesPage}" />

<ShellContent 
Title="Battery Current Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsBatteryCurrentPage}" />

<ShellContent 
Title="Battery Voltage Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsBatteryVoltagePage}" />

<ShellContent 
Title="Cedence Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsCadencePage}" />

<ShellContent 
Title="Human Power Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsHumanPowerPage}" />

<ShellContent 
Title="Motor Current Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsMotorCurrentPage}" />

<ShellContent 
Title="Motor FOC Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsMotorFOCPage}" />

<ShellContent 
Title="Motor Power Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsMotorPowerPage}" />

<ShellContent 
Title="Motor PWM Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsMotorPWMPage}" />

<ShellContent 
Title="Motor Speed Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsMotorSpeedPage}" />

<ShellContent 
Title="Motor Temperature Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsMotorTemperaturePage}" />

<ShellContent 
Title="Speed Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsSpeedPage}" />

<ShellContent 
Title="Trip Distance Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsTripDistancePage}" />

<ShellContent 
Title="Watts / Km Graph"
IsVisible="{Binding ShowGraphParameters}"
ContentTemplate="{DataTemplate graphvariables:VarsWattsKmPage}" />

</Shell>

视图模型/ControlMenuViewModel.cs

namespace TSDZ2Monitor;
public partial class ControlMenuViewModel : ObservableObject
{
[ObservableProperty]
bool showMainMenu = true;
[ObservableProperty]
bool showParameters = false;
[ObservableProperty]
bool showAssistLevels = false;
[ObservableProperty]
bool showGraphParameters = false;
public ICommand ShowParametersCommand => new Command(ChangeMenuControl);
public void ChangeMenuControl()
{
Console.WriteLine($"Before {ShowMainMenu} {ShowParameters} {ShowAssistLevels} {ShowGraphParameters}");
ShowMainMenu = !ShowMainMenu;
ShowParameters = !ShowParameters;
Console.WriteLine($"After  {ShowMainMenu} {ShowParameters}  {ShowAssistLevels} {ShowGraphParameters}");
}
}

我可以手动打开和关闭菜单,也可以通过显示页面上的按钮打开和关闭菜单(感谢ColeX -微软),但我在这里被难住了。很高兴听到任何想法,包括重构

哦,这是我对MenuItem做的

<MenuItem 
Text="Parameters - by menuitem"

Command="{Binding ShowParametersCommand}" />

我的应用程序崩溃了

[Choreographer] Skipped 984 frames!  The application may be doing too much work on its main thread.
**System.ArgumentOutOfRangeException:** 'Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')'
and then again

? ?在方法结束时更改MenuControl()失败。我不知道它指的是什么索引!

无论如何,我宁愿使用FlyoutItem,但如果需要的话,我会使用菜单项(也许这是一个更好的用例?

对不起,我知道这里有两个问题,但它们是联系在一起的。

G

我注意到,如果我设置IsVisible标志为false,那么我得到一个关于Active Shell Item未设置的错误。你有在你的Shell中添加任何Shell物品吗?

我怀疑IsVisible标志会导致渲染失败,如果在AppShell的第一个项目上设置false。xaml列表

我刚刚测试过,如果第一个项目附加到一个标志,那么我的应用程序崩溃,但是如果我不让第一个项目使用IsVisible标志,那么设计工作如预期。

这是使用MenuItem来控制项的显示。我仍然想要一个使用FlyoutItem的解决方案。

我可以尝试将shell列表中虚拟的第一项的文本值设置为空白。

变通办法,变通办法…

编辑:我在重读文档时注意到;

MenuItem类有一个Clicked事件和一个Command属性。因此,MenuItem对象使执行响应MenuItem被点击的动作的场景成为可能。 https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/shell/flyout

我猜我找错人了:(

我仍然遇到问题,无论使用的底层列表中的第一个项目都不存在-索引越界。

实验后的进一步编辑:

所以我创建了一个几乎空白的毛伊岛解决方案。我有一个基本的主页。

在AppShell中。我首先删除了ShellItem:

<Shell
x:Class="ShellItemsTest.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ShellItemsTest"
Shell.FlyoutBehavior="Flyout">

</Shell>

进入"break"模式并给出错误消息:

System.InvalidOperationException
Message=Active Shell Item not set. Have you added any Shell Items to your Shell?

好的,很好

然后我添加了一个新的Shell项并设置了它的属性IsVisible="False">

<ShellContent
Title="Home"
IsVisible="False"
ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage" />

这个也坏了,并给出了相同的信息。

我不知道该怎么想?这是故意的还是应该是一个bug。我倾向于认为后者,因为我的期望是有一个外壳项目,它只是不应该渲染?

然后我尝试了两个或三个shell项目,它们具有IsVisible true/false的不同组合。

结果似乎是,如果没有项目是可见的,那么得到一个中断和错误。

如果至少有一个项目设置可见,无论在什么位置都ok。

如果两项设置为false,第三项设置为true,则应用程序运行,但如果我将第三项更改为false(在热加载下),则应用程序进入中断模式,我也看到错误:

**System.ArgumentOutOfRangeException:** 'Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')'

这个故事的寓意似乎是,您必须在任何时候至少有一个弹出项可见。

我不知道这里是否有任何时间问题——它是异步工作的吗?

我将在github中为。net maui提出一个报告,看看开发人员怎么说。:) G

我在shell的文档中注意到(最后)这个小gem:

Note: 
There's also a Shell.FlyoutItemIsVisible attached property, which can be set on FlyoutItem, MenuItem, Tab, and ShellContent objects.

实际上这里有很多属性在操作:

Flyout items are visible in the flyout by default. However, an item can be hidden in the flyout with the FlyoutItemIsVisible property, and removed from the flyout with the IsVisible property:

和shell。刚才提到的FlyoutItemIsVisible

使用这个解决了我的问题。哎!

最新更新