如何在内容视图的 Android 应用程序中将开关绑定到 Xamarin 中的 属性?

How do I bind a switch to a property in Xamarin in an Android app in a content view?

我正在使用 Xamarin 在 VS 2022 中创建我的第一个 Android 应用程序,现在我必须将一个开关绑定到一个标签以向用户显示 on/off 的含义。多次所以我做了一个内容视图:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:controls="clr-namespace:App1.Controls" x:DataType="controls:SwitchWithText"
             x:Class="App1.Controls.SwitchWithText"
             x:Name="root">
  <ContentView.Content>
      <StackLayout Orientation="Horizontal">
          <Label x:Name="isOkLbl" Text="is not ok" Margin="10"/>
          <Switch x:Name="switch1" IsToggled="{Binding Path=IsToggled}"/>
        </StackLayout>
  </ContentView.Content>
</ContentView>
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace App1.Controls
{
  [XamlCompilation(XamlCompilationOptions.Compile)]
  public partial class SwitchWithText : ContentView
  {

    public static readonly BindableProperty isToggledProperty = BindableProperty.Create(
      nameof(isToggledProperty),    //name of property
      typeof(bool),                 //type of property
      typeof(SwitchWithText),       //type of owning object
      defaultValue: false,
      propertyChanged: IsToggledChanged);

    public bool IsToggled
    {
      get => (bool)GetValue(isToggledProperty);
      set => SetValue(isToggledProperty, value);
    }

    private static void IsToggledChanged(BindableObject bindable, object oldValue, object newValue)
    {
      var control = (SwitchWithText)bindable;
      if (control != null && control.switch1.IsToggled)
      {
        control.isOkLbl.Text = "is ok";
      }
      else
      {
        control.isOkLbl.Text = "is not ok";
      }
    }
    public SwitchWithText()
    {
      BindingContext = this;
      InitializeComponent();
    }
  }
}

有些东西会在 Visual Studio 2022 年自动完成,看起来它会做我需要的,但当我切换开关时没有任何反应。 :( 还是有更好的方法来做到这一点?我看到了带有文字的开关图片,但在 Xamarin 中找不到类似的东西。

这是您想要的结果吗?

我认为您可能想要的是一个值转换器 class,它将采用 IsToggled 绑定并将其转换为标签的字符串。如果您想查看功能演示,我 post 在 GitHub 上编辑了工作代码。 (我将它直接放在 xaml 中用于 ContentPage,但当然同样的原理也适用于 ContentView 和你的 post。)

using System;
using System.Globalization;
using Xamarin.Forms;

namespace App1
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            BindingContext = this;
            InitializeComponent();
        }
        bool _IsToggled = false;
        public bool IsToggled
        {
            get => _IsToggled;
            set
            {
                if (_IsToggled != value)
                {
                    _IsToggled = value;
                    OnPropertyChanged(nameof(IsToggled));
                }
            }
        }
    }

    /// <summary>
    /// Value converter class
    /// </summary>
    public class BoolToTextConverter : IValueConverter
    {
        public string IfFalse { get; set; }
        public string IfTrue { get; set; }

        public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if ((bool)value)
            {
                return IfTrue;
            }
            else
            {
                return IfFalse;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

然后要使用值转换器,您可以在 xaml 中将其设为静态资源,如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:app1="clr-namespace:App1"
             x:Class="App1.MainPage">

    <ContentPage.Resources>
        <app1:BoolToTextConverter x:Key="SwitchToText"
                                 IfTrue="is ok"
                                 IfFalse="is not ok" />
    </ContentPage.Resources>
    <StackLayout>
        <Label Text="{Binding Path=IsToggled, Converter={StaticResource SwitchToText}}" FontSize="Title" Padding="30,10,30,10"/>
        <Switch x:Name="switch1"
                IsToggled="{Binding Path=IsToggled}" />
    </StackLayout>

</ContentPage>

所以我的建议是尝试使用值转换器来执行您想要的操作。