如何将不同类中的两个 Switch 控件绑定到同一个 bool 属性?
Posted
技术标签:
【中文标题】如何将不同类中的两个 Switch 控件绑定到同一个 bool 属性?【英文标题】:How to bind two Switch controls in separate classes to the same bool property? 【发布时间】:2021-12-29 18:56:34 【问题描述】:我正在创建一个首选项中心,该中心需要为两个具有相同布尔/切换值的单独切换切换同步更新。我正在使用带有 C# 的 Xamarin 表单。我有一个 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.xaml 和 AllowSaleToggleTab.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"/>
但它们仍然不同步。谁能指出我做错了什么?谢谢
【问题讨论】:
每个页面都有自己的虚拟机实例。同一类的多个实例完全相互独立 您创建不同的 ViewModel 实例,每个实例用于每个页面。两个页面都应该是单一的。就像我之前对 WPF 的回答一样,我在一个窗口中创建实例,然后将其作为参数传递给其他两个,因此它们使用相同的 ViewModel(此处:***.com/questions/69934877/…) 啊,这是有道理的,但是我的 XamarinDemoApp.android 包中有一个 MainActivity.cs,我的 XamarinDemoApp 包中有一个 App.xaml.cs 文件。我应该在哪里创建父实例? 如果两个页面都在 Forms 项目中,把它放在那里。你也可以使用单例模式,或者创建一个静态类等。有很多方法可以解决这个问题。 【参考方案1】:我知道的最简单的方法是使用静态对象。
变量持有人:
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 = "我正在更新此字符串";您在两个位置都会获得更新的字符串。确保您已安装 propertychanged.fody nuget。
【讨论】:
【参考方案2】:我不知道你的代码是如何使用的,但是有几种方法可以实现。
例如,您可以在导航时在两个不同的Page之间传递数据,或者使用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.我为两个页面使用了两个不同的ViewModel(TestPage1
和TestPage2
),TestPage1的ViewModel是MyViewModel
,TestPage1的ViewModel是MyViewModel2
。
2.改变TestPage1
中Switch
的状态后,我们可以通过构造函数将MyViewModel.cs
中的SwithOne
值传递给TestPage2
:
private async void Button_Clicked(object sender, EventArgs e)
await Navigation.PushAsync( new TestPage2(myViewModel.SwithOne));//myViewModel.SwithOne
3.如果我们改变TestPage2
中SwithTwo
的值,我们可以使用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
【讨论】:
以上是关于如何将不同类中的两个 Switch 控件绑定到同一个 bool 属性?的主要内容,如果未能解决你的问题,请参考以下文章
Android 多个控件绑定同一个PopupWindow,当点击popupWindow中的控件时获取到触发popWindow控件的文本