.net Maui 数据绑定到 shell 弹出项目 IsVisible 属性
.net Maui databinding to shell flyout item IsVisible property
所以我有一个弹出式菜单,我需要让弹出式菜单项在特定条件下消失。为了帮助我发展我的想法和理解,我有一个包含 6 个项目的弹出窗口,其中一个标题为蓝牙。我在我的第一个弹出页面中创建了一个名为 ShowParameters 的按钮。我可以使它使视图模型中的 属性 为真或假。这似乎工作正常。我已将蓝牙弹出项目的 IsVisible 属性 绑定到此 ShowParameters 属性。这不会在单击按钮时更新 IsVisible 属性。似乎 PropertyChanged?.Invoke 未链接到 Flyout 项或 Flyout 项未链接到 属性,但我可以使它在 xaml 本身内出现或消失。很明显,我对这些东西一窍不通,我做了一些非常愚蠢的事情。有人能指出我有多愚蠢吗 ;)
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"
Shell.FlyoutBehavior="Flyout"
FlyoutHeaderBehavior="Default"
FlyoutVerticalScrollMode="Auto"
FlyoutBackgroundColor="{StaticResource FlyoutBackgroundColor}">
<Shell.BindingContext>
<local:ShowParametersViewModel/>
</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 ShowParameters}"
ContentTemplate="{DataTemplate pages:BluetoothPage}" />
<ShellContent
Title="About"
Icon="about.svg"
ContentTemplate="{DataTemplate pages:AboutPage}" />
</Shell>
DisplayPage.xaml 在文件夹 Pages
中
<?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:TSDZ2Monitor"
x:Class="TSDZ2Monitor.Pages.DisplayPage"
Title="Display Page">
<ContentPage.BindingContext>
<local:ShowParametersViewModel />
</ContentPage.BindingContext>
<StackLayout>
<Label Text="Main Display"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Button Text="Show parameters"
FontSize="20"
Command="{Binding ShowParametersCommand}"/>
</StackLayout>
</ContentPage>
我的 ShowParametersViewModel.cs(在文件夹 ViewModels 中)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace TSDZ2Monitor
{
//public class ShowParametersViewModel : BindableObject
public class ShowParametersViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
bool showParameters = true;
public bool ShowParameters
{
get { return showParameters; }
set
{
if (value == showParameters) return;
showParameters = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ShowParameters"));
}
}
public ICommand ShowParametersCommand => new Command(ChangeShowParameters);
public void ChangeShowParameters()
{
Console.WriteLine($"Before {ShowParameters}");
ShowParameters = !ShowParameters;
Console.WriteLine($"After {ShowParameters}");
}
}
}
如果我将 AppShell.xaml 中的 Shell.BindingContext 更改为
<Shell.BindingContext>
<local:ShowParametersViewModel ShowParameters="false"/>
</Shell.BindingContext>
它使蓝牙弹出菜单项消失,反之亦然
现在您可能想查看存储库 https://github.com/gfmoore/TSDZ2Monitor 但这很可能会改变。
出现此问题是因为您在页面之间操作不同的数据(viewmodel),但我们需要共享数据。
以下两部分代码完全相同。
<Shell.BindingContext>
<local:ShowParametersViewModel />
</Shell.BindingContext>
public AppShell()
{
InitializeComponent();
BindingContext = new ShowParametersViewModel();
}
实际上它创建了一个 new instance
的视图模型 class ,并将其设置为 BindingContext,与 DisplayPage 中的方式相同。
所以有两个不同的视图模型,您只需更改 A,但 B 永远不会更改。
解决方案
在隐藏代码中而不是在 xaml(DisplayPage ) 中初始化 ShowParametersViewModel
,以便它们共享相同的视图模型。
public DisplayPage ()
{
InitializeComponent();
this.BindingContext = AppShell.Current.BindingContext;
}
所以我有一个弹出式菜单,我需要让弹出式菜单项在特定条件下消失。为了帮助我发展我的想法和理解,我有一个包含 6 个项目的弹出窗口,其中一个标题为蓝牙。我在我的第一个弹出页面中创建了一个名为 ShowParameters 的按钮。我可以使它使视图模型中的 属性 为真或假。这似乎工作正常。我已将蓝牙弹出项目的 IsVisible 属性 绑定到此 ShowParameters 属性。这不会在单击按钮时更新 IsVisible 属性。似乎 PropertyChanged?.Invoke 未链接到 Flyout 项或 Flyout 项未链接到 属性,但我可以使它在 xaml 本身内出现或消失。很明显,我对这些东西一窍不通,我做了一些非常愚蠢的事情。有人能指出我有多愚蠢吗 ;)
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"
Shell.FlyoutBehavior="Flyout"
FlyoutHeaderBehavior="Default"
FlyoutVerticalScrollMode="Auto"
FlyoutBackgroundColor="{StaticResource FlyoutBackgroundColor}">
<Shell.BindingContext>
<local:ShowParametersViewModel/>
</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 ShowParameters}"
ContentTemplate="{DataTemplate pages:BluetoothPage}" />
<ShellContent
Title="About"
Icon="about.svg"
ContentTemplate="{DataTemplate pages:AboutPage}" />
</Shell>
DisplayPage.xaml 在文件夹 Pages
中<?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:TSDZ2Monitor"
x:Class="TSDZ2Monitor.Pages.DisplayPage"
Title="Display Page">
<ContentPage.BindingContext>
<local:ShowParametersViewModel />
</ContentPage.BindingContext>
<StackLayout>
<Label Text="Main Display"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Button Text="Show parameters"
FontSize="20"
Command="{Binding ShowParametersCommand}"/>
</StackLayout>
</ContentPage>
我的 ShowParametersViewModel.cs(在文件夹 ViewModels 中)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace TSDZ2Monitor
{
//public class ShowParametersViewModel : BindableObject
public class ShowParametersViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
bool showParameters = true;
public bool ShowParameters
{
get { return showParameters; }
set
{
if (value == showParameters) return;
showParameters = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ShowParameters"));
}
}
public ICommand ShowParametersCommand => new Command(ChangeShowParameters);
public void ChangeShowParameters()
{
Console.WriteLine($"Before {ShowParameters}");
ShowParameters = !ShowParameters;
Console.WriteLine($"After {ShowParameters}");
}
}
}
如果我将 AppShell.xaml 中的 Shell.BindingContext 更改为
<Shell.BindingContext>
<local:ShowParametersViewModel ShowParameters="false"/>
</Shell.BindingContext>
它使蓝牙弹出菜单项消失,反之亦然
现在您可能想查看存储库 https://github.com/gfmoore/TSDZ2Monitor 但这很可能会改变。
出现此问题是因为您在页面之间操作不同的数据(viewmodel),但我们需要共享数据。
以下两部分代码完全相同。
<Shell.BindingContext>
<local:ShowParametersViewModel />
</Shell.BindingContext>
public AppShell()
{
InitializeComponent();
BindingContext = new ShowParametersViewModel();
}
实际上它创建了一个 new instance
的视图模型 class ,并将其设置为 BindingContext,与 DisplayPage 中的方式相同。
所以有两个不同的视图模型,您只需更改 A,但 B 永远不会更改。
解决方案
在隐藏代码中而不是在 xaml(DisplayPage ) 中初始化 ShowParametersViewModel
,以便它们共享相同的视图模型。
public DisplayPage ()
{
InitializeComponent();
this.BindingContext = AppShell.Current.BindingContext;
}