如何将单独 类 中的两个 Switch 控件绑定到同一个 bool 属性?

How to bind two Switch controls in separate classes to the same bool property?

我正在制作一个偏好中心,它需要为两个具有相同布尔值/切换值的独立开关切换同步更新。我在 C# 中使用 Xamarin Forms。我有一个 ViewModel.cs 文件,例如

namespace XamarinDemoApp
public class MyViewModel : INotifyPropertyChanged
{
    private bool swithOne;
    public bool SwithOne
    {
        set
        {
            if (swithOne != value)
            {
                swithOne = value;
                OnPropertyChanged("SwithOne");
            }
        }
        get
        {
            return swithOne;
        }
    }

public MyViewModel()
    {
        SwithOne = true; // assign a value for `SwithOne `
    }

    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    }
}

然后我的AllowSaleToggleTab.xaml.cs看起来像

namespace XamarinDemoApp
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class AllowSaleToggleTab : ContentPage
{
    MyViewModel myViewModel;
    public AllowSaleToggleTab()
    {
        InitializeComponent();
        myViewModel = new MyViewModel();
        BindingContext = myViewModel;
    }
}
}

另一个切换选项卡是 PC.xaml.cs

namespace XamarinDemoApp
{
[XamlCompilation(XamlCompilationOptions.Compile)]

public partial class PC : ContentPage
{
    MyViewModel myViewModel;

    public PC()
    {
        InitializeComponent();
        Console.WriteLine("PC Initialized");
        myViewModel = new MyViewModel();
        BindingContext = myViewModel;
    }
}
}

最后,我随附的 PC.xamlAllowSaleToggleTab.xaml 文件都包含以下元素

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:xamarindemoapp="clr-namespace:XamarinDemoApp" x:DataType="xamarindemoapp:MyViewModel"
             x:Class="XamarinDemoApp.AllowSaleToggleTab">
    <Switch x:Name="ToggleSwitch1"  IsToggled="{Binding SwithOne}"/>

但他们仍然不同步。谁能指出我做错了什么?谢谢

不知道你的代码是怎么用的,不过有几种方法可以实现。

例如,您可以在导航时在两个不同的页面之间传递数据,或者使用Xamarin.Forms MessagingCenter在两个页面之间发送数据消息。

可以参考下面的代码(我结合了上面的两种方法):

TestPage1.xaml

<ContentPage.Content>
    <StackLayout>
        <Switch x:Name="toggleSwitch1" IsToggled="{Binding SwithOne}"   HorizontalOptions="Center">
        </Switch>
        <Button  Text="navigate to Page2"  Clicked="Button_Clicked"/>
    </StackLayout>
</ContentPage.Content>

TestPage1.xaml.cs

public partial class TestPage1 : ContentPage
{
     MyViewModel myViewModel;
    public TestPage1()
    {
        InitializeComponent();

        myViewModel = new MyViewModel();
        BindingContext = myViewModel;
    }
    private async void Button_Clicked(object sender, EventArgs e)
    {
        await Navigation.PushAsync( new TestPage2(myViewModel.SwithOne));//myViewModel.SwithOne
    }
}

MyViewModel.cs

public  class MyViewModel: INotifyPropertyChanged
{       
    private  bool _swithOne { get; set; }
    public  bool SwithOne
    {
        set
        {
            if (_swithOne != value)
            {
                _swithOne = value;
                OnPropertyChanged("SwithOne");

            }
        }
        get
        {
            return _swithOne;
        }
    }

    public MyViewModel()
    {
        SwithOne = true;

        MessagingCenter.Subscribe<object, object>(this, "PassDataToOne", (sender, args) =>
        {
            bool value = (bool)args;

            if (value!= SwithOne) {

                SwithOne = value;
            }
          
        });
    }

    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    protected   void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

}

TestPage2.xaml

<ContentPage.Content>
    <StackLayout>
        <Switch x:Name="toggleSwitch2" IsToggled="{Binding SwithTwo}"   HorizontalOptions="Center" />

        <Button  Text="Navigate To  Page 1" Clicked="Button_Clicked"/>
    </StackLayout>
</ContentPage.Content>

TestPage2.xaml.cs

public partial class TestPage2 : ContentPage
{
    MyViewModel2 myViewModel;

    public TestPage2(bool isToggled)
    {
        InitializeComponent();

         myViewModel = new MyViewModel2(isToggled);

        BindingContext = myViewModel;
    }

    private async void Button_Clicked(object sender, EventArgs e)
    {
        await Navigation.PopAsync();
    }
}

MyViewModel2.cs

public class MyViewModel2: INotifyPropertyChanged
{
    private bool _swithTwo;
    public bool SwithTwo
    {
        set
        {
            if (_swithTwo != value)
            {
                _swithTwo = value;
                OnPropertyChanged("SwithTwo");

                MessagingCenter.Send<object, object>(this, "PassDataToOne", _swithTwo);

            }
        }
        get
        {
            return _swithTwo;
        }
    }

    public MyViewModel2( bool isToggled)
    {
        SwithTwo = isToggled;
    }


    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

注:

1.I两个页面使用了两个不同的ViewModel(TestPage1TestPage2),TestPage1的ViewModel是MyViewModel,TestPage1的ViewModel是MyViewModel2 .

2.After改变TestPage1Switch的状态,我们可以通过MyViewModel.cs中的值SwithOne传递给TestPage2构造函数:

    private async void Button_Clicked(object sender, EventArgs e)
    {
        await Navigation.PushAsync( new TestPage2(myViewModel.SwithOne));//myViewModel.SwithOne
    }

3.If我们把SwithTwo的值改成TestPage2,我们可以用MessagingCenter把值传给TestPage1

   public class MyViewModel2: INotifyPropertyChanged
{
    private bool _swithTwo;
    public bool SwithTwo
    {
        set
        {
            if (_swithTwo != value)
            {
                _swithTwo = value;
                OnPropertyChanged("SwithTwo");

                MessagingCenter.Send<object, object>(this, "PassDataToOne", _swithTwo);

            }
        }
        get
        {
            return _swithTwo;
        }
    }
// other code
}

我知道的最简单的方法是使用静态对象。

变量持有人:

public class SomeClass : INotifyPropertyChanged
{
public static SomeClass Instance {get;set;} = new SomeClass();

public string SharedString {get;set;}

#region The rest of property changed
...
#endregion
}

查看 1

<Label Text={Binding Path=SharedString, Source={x:Static locationOfSomeClass:SomeClass.Instance}} />

查看 2

<Label Text={Binding Path=SharedString, Source={x:Static locationOfSomeClass:SomeClass.Instance}} />

每当您更改字符串时,例如 SomeClass.Instance.SharedString = "I'm updating this string";您会在这两个位置获得更新的字符串。确保安装了 propertychanged.fody nuget。