我有一个用于按钮的模板。我将其中四个按钮放在这样的页面上:
<template:Button Meta="gst" Grid.Column="1" Selected="{Binding Mode[0].Selected}" Text="{Binding Mode[0].Name}" TapCommand="{Binding ModeBtnCmd }" />
<template:Button Meta="gst" Grid.Column="2" Selected="{Binding Mode[1].Selected}" Text="{Binding Mode[1].Name}" TapCommand="{Binding ModeBtnCmd }" />
<template:Button Meta="gst" Grid.Column="3" Selected="{Binding Mode[2].Selected}" Text="{Binding Mode[2].Name}" TapCommand="{Binding ModeBtnCmd }" />
<template:Button Meta="gst" Grid.Column="4" Selected="{Binding Mode[3].Selected}" Text="{Binding Mode[3].Name}" TapCommand="{Binding ModeBtnCmd }" />
我声明了一个名为Mode的数组,该数组用于将Selected参数的一些值存储在这样声明的数组中:
public partial class HomePageViewModel : ObservableObject
{
ParamViewModel[] _mode;
public ParamViewModel[] Mode { get => _mode; set => SetProperty(ref _mode, value); }
在OnAppearing中,我为数组中的每个元素设置Selected的值:
protected async override void OnAppearing()
{
base.OnAppearing();
vm.Mode[0].Selected = false;
vm.Mode[1].Selected = false;
vm.Mode[2].Selected = true;
vm.Mode[3].Selected = false;
但是,我没有看到每个按钮需要HandleSelectedPropertyChanged。如果在HandleSelectedPropertyChanged事件中设置调试点,则只会看到它被调用一次。
我希望只选择第三个按钮,但是当代码运行时,按钮显示为:
已选择已选择已选择已选择
有人可以给我建议吗? 当我一个接一个地单击按钮时,代码起作用,并且后端更改了所选内容,然后调用了上面的SetButtons。但这最初并不起作用,并且所有按钮都显示为选中状态。
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Japanese.Templates
{
public partial class Button : Frame
{
public static readonly BindableProperty TapCommandProperty = BindableProperty.Create("TapCommand", typeof(Command), typeof(Button), defaultBindingMode: BindingMode.TwoWay, defaultValue: default(Command));
public static readonly BindableProperty TapCommandParamProperty = BindableProperty.Create(nameof(TapCommandParam), typeof(object), typeof(Button), default(object));
public static readonly BindableProperty
SelectedProperty = BindableProperty.Create(nameof(Selected),
typeof(bool),
typeof(Button),
false,
propertyChanged: HandleSelectedPropertyChanged);
public static readonly BindableProperty
TextProperty = BindableProperty.Create(nameof(Text),
typeof(string),
typeof(Button),
default(string));
public static readonly BindableProperty
MetaProperty = BindableProperty.Create("Meta",
typeof(string),
typeof(Button),
default(string),
propertyChanged: HandleMetaPropertyChanged);
public static readonly BindableProperty VisibleProperty = BindableProperty.Create(nameof(Visible), typeof(bool), typeof(Button), true);
public string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); }
public string Meta { get => (string)GetValue(MetaProperty); set => SetValue(MetaProperty, value); }
public Command TapCommand { get => (Command)GetValue(TapCommandProperty); set => SetValue(TapCommandProperty, value); }
public object TapCommandParam { get => (object)GetValue(TapCommandParamProperty); set => SetValue(TapCommandParamProperty, value); }
public bool Selected { get => (bool)GetValue(SelectedProperty); set => SetValue(SelectedProperty, value); }
public bool Visible { get => (bool)GetValue(VisibleProperty); set => SetValue(VisibleProperty, value); }
string b;
string s;
string f;
public Button()
{
InitializeComponent();
HasShadow = false;
HorizontalOptions = LayoutOptions.Center;
VerticalOptions = LayoutOptions.Center;
}
private static void HandleMetaPropertyChanged(BindableObject bindable, object oldValue, object meta)
{
var control = (Button)bindable;
if (control != null) {
control.b = ((string)meta).Substring(0, 1); // background surface
control.s = ((string)meta).Substring(1, 1); // shape
control.f = ((string)meta).Substring(2, 1); // font
control.BackgroundColor = control.b == "g" ?
(Color)Application.Current.Resources["GridButtonBackgroundColor"] :
(Color)Application.Current.Resources["PageButtonBackgroundColor"];
control.BorderColor = control.b == "g" ?
(Color)Application.Current.Resources["GridButtonBorderColor"] :
(Color)Application.Current.Resources["PageButtonBorderColor"];
if (control.s == "s")
{
control.CornerRadius = 5;
control.Padding = new Thickness(10, 5);
}
else
{
control.WidthRequest = 50;
control.HeightRequest = 50;
control.CornerRadius = 25;
control.Padding = new Thickness(0);
}
Application.Current.Resources.TryGetValue("TextButtonsLabelRes", out object textRes);
Application.Current.Resources.TryGetValue("IconButtonsLabelRes", out object iconRes);
control.ButtonLabel.Style = (control.f == "t") ?
(Style)textRes :
(Style)iconRes;
}
}
private static void HandleSelectedPropertyChanged(BindableObject bindable, object oldValue, object selected)
{
var control = (Button)bindable;
if (control != null)
control.ButtonLabel.TextColor =
((bool)selected) ?
(control.b == "g" ?
(Color)Application.Current.Resources["GridEButtonTextColor"] :
(Color)Application.Current.Resources["PageEButtonTextColor"]) :
(control.b == "g" ?
(Color)Application.Current.Resources["GridButtonTextColor"] :
(Color)Application.Current.Resources["PageButtonTextColor"]);
}
private async void ChangeTheColours(Object sender, EventArgs e)
{
if ((string)this.ButtonLabel.Text.Substring(0, 1) != " ")
{
BackgroundColor = this.b == "g" ?
(Color)Application.Current.Resources["GridCButtonBackgroundColor"] :
(Color)Application.Current.Resources["PageCButtonBackgroundColor"];
BorderColor = this.b == "g" ?
(Color)Application.Current.Resources["GridCButtonBorderColor"] :
(Color)Application.Current.Resources["PageCButtonBorderColor"];
await Task.Delay(500);
BackgroundColor = this.b == "g" ?
(Color)Application.Current.Resources["GridButtonBackgroundColor"] :
(Color)Application.Current.Resources["PageButtonBackgroundColor"];
BorderColor = this.b == "g" ?
(Color)Application.Current.Resources["GridButtonBorderColor"] :
(Color)Application.Current.Resources["PageButtonBorderColor"];
}
}
}
}
下面是SetProperty函数供参考:
public class ObservableObject : INotifyPropertyChanged
{
protected virtual bool SetProperty<T>(
ref T backingStore, T value,
[CallerMemberName]string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
提醒一下,这里的代码和方法运行良好,但初始设置似乎并未按预期调用propertyChanged事件。
答案 0 :(得分:0)
您的SelectedProperty
的默认值为false,仅当当前值与新值不同时才会触发OnPropertyChanged
。因此,仅触发其值设置为true
的第三个按钮。
您必须在控件的构造函数中定义控件的初始状态。更改任何属性后,后续更改将在PropertyChanged
处理程序中处理