如何将单独 类 中的两个 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.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}"/>
但他们仍然不同步。谁能指出我做错了什么?谢谢
不知道你的代码是怎么用的,不过有几种方法可以实现。
例如,您可以在导航时在两个不同的页面之间传递数据,或者使用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(TestPage1
和TestPage2
),TestPage1的ViewModel是MyViewModel
,TestPage1的ViewModel是MyViewModel2
.
2.After改变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.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。
我正在制作一个偏好中心,它需要为两个具有相同布尔值/切换值的独立开关切换同步更新。我在 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.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}"/>
但他们仍然不同步。谁能指出我做错了什么?谢谢
不知道你的代码是怎么用的,不过有几种方法可以实现。
例如,您可以在导航时在两个不同的页面之间传递数据,或者使用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(TestPage1
和TestPage2
),TestPage1的ViewModel是MyViewModel
,TestPage1的ViewModel是MyViewModel2
.
2.After改变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.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。