.NET MAUI 跨页面共享 ContentView 中的数据

问题描述 投票:0回答:1

我是 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 上下文。 谢谢!

c# xaml mobile maui
1个回答
0
投票

你的问题的措辞是关于跨页面共享来自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;
}
App.xaml.cs中的拦截

在共享数据开关切换的一般意义上,该操作将来到这里。此时的几个选项之一是在

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.