我是 MAUI 的菜鸟,我正在为 Android 和 iOS 开发一个应用程序。我有一个简单的 ContentView,它只是一个带有开关的横幅,我将其包含在我的应用程序的几个页面中。我的 xaml 看起来像这样:
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp.Partials"
x:Class="MyApp.Partials.Banner"
x:DataType="local:Banner"
x:Name="BannerView">
<Grid BackgroundColor="Yellow">
<HorizontalStackLayout
HorizontalOptions="CenterAndExpand"
VerticalOptions="Center">
<Image Source="smartphone.png" HeightRequest="40" Aspect="AspectFit" />
<Switch IsToggled="{Binding Source={x:Reference BannerView}, Path=IsSwitchToggled}" />
<Image Source="lightning.png" HeightRequest="40" Aspect="AspectFit" />
</HorizontalStackLayout>
</Grid>
</ContentView>
背后的代码:
public partial class Banner : ContentView
{
public Banner()
{
InitializeComponent();
}
public bool IsSwitchToggled
{
get => (bool)GetValue(IsSwitchToggledProperty);
set => SetValue(IsSwitchToggledProperty, value);
}
public static readonly BindableProperty IsSwitchToggledProperty = BindableProperty.Create(
nameof(IsSwitchToggled),
typeof(bool),
typeof(Banner),
false,
propertyChanged: OnIsSwitchToggled);
static void OnIsSwitchToggled(BindableObject bindable, object oldValue, object newValue)
{
Console.WriteLine("Toggle value: " + newValue);
}
}
然后我将其包含在我的其他 xaml 页面中:
<StackLayout>
<partials:Banner />
<Label Text="Mainpage" />
</StackLayout>
稍后我希望此开关控制应用程序的颜色(如果开关设置为 false,则为一种特定颜色;如果设置为 true,则为另一种颜色)。 我的问题是,我希望在不同页面上维护开关的值,但我不确定可绑定属性是否是解决问题的正确方法。
我的第一个方法有点不同。我有一堂课,里面有我的布尔值:
public class SharedData : INotifyPropertyChanged
{
private bool _isSwitchToggled;
public bool IsSwitchToggled
{
get { return _isSwitchToggled; }
set
{
if (_isSwitchToggled != value)
{
_isSwitchToggled = value;
OnPropertyChanged(nameof(IsSwitchToggled));
}
}
}
// Other stuff
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
但是当我意识到 ContentView 构造函数无法传递参数时,我遇到了困难。
我有更多的 React 背景,所以我想我所要求的有点像传递数据的 React 上下文。 谢谢!
你的问题的措辞是关于跨页面共享来自ContentView的数据,但我真正注意到的是当你提到这个目标时:
我想要这个开关来控制应用程序的颜色。
因此,我选择直接解决“Y 问题”,这也将提供一种处理更一般情况的方法。因此,就应用程序颜色而言,默认的 Maui 项目模板附带了浅色和深色的动态主题,可以在 Styles.xaml 文件中根据您的喜好进行自定义。因此,在第一个近似值中,我们只需利用该机制即可早点回家:
public partial class Banner : ContentView
{
public Banner() => InitializeComponent();
public bool IsSwitchToggled
{
get => _isSwitchToggled;
set
{
if (!Equals(_isSwitchToggled, value))
{
_isSwitchToggled = value;
if (App.Current is App app)
{
app.UserAppTheme =
_isSwitchToggled ?
AppTheme.Dark :
AppTheme.Light;
}
}
}
}
bool _isSwitchToggled = default;
}
自定义主题拦截
您的另一个选择是拦截该属性以注入您自己的主题。
enum CustomAppTheme
{
Light,
Dark,
Warm,
}
public partial class Banner : ContentView
{
public Banner() => InitializeComponent();
public bool IsSwitchToggled
{
get => _isSwitchToggled;
set
{
if (!Equals(_isSwitchToggled, value))
{
_isSwitchToggled = value;
((App)App.Current!).UserAppTheme =
_isSwitchToggled ?
CustomAppTheme.Warm :
CustomAppTheme.Light;
}
}
}
bool _isSwitchToggled = default;
}
在共享数据开关切换的一般意义上,该操作将来到这里。此时的几个选项之一是在
UserThemeChanged
级别创建可绑定的 App
属性,并将各个子页面绑定到该属性更改,并且可能重新分配页面视图的 Style
属性以适应改变。
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
}
public new Enum UserAppTheme
{
get => _userAppTheme;
set
{
if (!Equals(_userAppTheme, value))
{
_userAppTheme = value;
switch (value)
{
case AppTheme.Light:
case CustomAppTheme.Light:
base.UserAppTheme = AppTheme.Light;
break;
case AppTheme.Dark:
case CustomAppTheme.Dark:
base.UserAppTheme = AppTheme.Dark;
break;
default:
_ = MainPage?.DisplayAlert("ThemeChange", $"{value}", "OK");
break;
}
OnPropertyChanged();
}
}
}
Enum _userAppTheme = AppTheme.Light;
}