在WinPHone 8.1上使用Xamarin.Forms基于触发器更改样式

时间:2018-01-30 09:31:08

标签: xamarin xamarin.forms windows-phone-8.1

我有以下风格

<Style x:Key="GreenButtonStyle" BasedOn="{StaticResource MyButtonBaseStyle}" TargetType="Button">
    <Style.Triggers>
        <Trigger TargetType="Button" Property="IsEnabled" Value="False">
            <Setter Property="BackgroundColor" Value="Silver" />
            <Setter Property="TextColor" Value="Black" />
        </Trigger>
        <Trigger TargetType="Button" Property="IsEnabled" Value="True">
            <Setter Property="BackgroundColor" Value="Green" />
            <Setter Property="TextColor" Value="Orange" />
        </Trigger>
    </Style.Triggers>
</Style>

我在以下视图中使用。

<Button x:Name="ConfirmButton" 
    Text="Confirm" 
    Style="{StaticResource GreenButtonStyle}" 
    IsEnabled="{Binding Source={x:Reference Some}, Path=ConfirmEnabled}"
    /> 
<Button x:Name="ToggleButton"
    Text="Toggle" 
    Clicked="Toggle_Clicked"
    />

后面的代码(只是片段)

public partial class SomeView : ContentPage, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool _confirmEnabled = false;
    public bool ConfirmEnabled
    {
        get { return _confirmEnabled; }
    }

    private void Toggle_Clicked(object sender, EventArgs e)
    {
        _confirmEnabled = !_confirmEnabled;
        PropertyChanged(this, new PropertyChangedEventArgs(nameof(ConfirmEnabled)));
    }
}

当View进入游戏状态时,按钮处于非活动状态时一切正常。当我单击切换按钮时,字体会根据需要将颜色更改为橙​​色,但背景不会将颜色更改为绿色。

如果我单击两次切换(禁用然后启用),则字体为橙色,背景最终为绿色。

任何人都知道为什么在第一次将ConfirmEnabled更改为true时背景颜色没有改变?

2 个答案:

答案 0 :(得分:0)

我建议您使用MVVM方法进行应用设计。创建一个名为BaseViewModel.cs的类和另一个名为SomeViewModel.cs的类,并按如下方式编写它们:

BaseViewModel.cs,每个视图模型都应该继承。它允许您使用PropertyChanged个事件:

public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

SomeViewModel.cs。现在每次更改ConfirmEnabled的值时,一旦设置了绑定,视图就会自动检测到更改:

public class SomeViewModel : BaseViewModel
{
    private bool _confirmEnabled = false;

    public bool ConfirmEnabled
    {
        get { return _confirmEnabled; }
        set 
        { 
            _confirmEnabled = value;
            OnPropertyChanged(nameof(ConfirmEnabled));
        }
    }
}

现在,对于你的页面SomeView.cs:

public partial class SomeView : ContentPage, INotifyPropertyChanged
{
    SomeViewModel _viewModel;

    public SomeView()
    {
        InitializeComponent();
        _viewModel = new SomeViewModel();
        BindingContext = _viewModel;
    }

    private void Toggle_Clicked(object sender, EventArgs e)
    {
        _viewModel.ConfirmEnabled = !_viewModel.ConfirmEnabled;
    }
}

你的按钮代码:

    <Button x:Name="ConfirmButton" 
        Text="Confirm" 
        Style="{StaticResource GreenButtonStyle}" 
        IsEnabled="{Binding ConfirmEnabled}"
        /> 
    <Button x:Name="ToggleButton"
        Text="Toggle" 
        Clicked="Toggle_Clicked"
        />

答案 1 :(得分:0)

结束实现我自己的按钮控制,它基本上是两个按钮,然后根据它是启用还是禁用我隐藏或显示另一个。

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyProject.Views._Controls.MyButton">

    <Grid>
        <Button x:Name="WhenEnabledButton"
                Clicked="WhenEnabledButton_Clicked"
                Text="WhenEnabled"></Button>
        <Button x:Name="WhenDisabledButton"
                Text="WhenDisabled"></Button>
        <Label x:Name="DisabledButtonCoveringLabel" BackgroundColor="Transparent"></Label>
    </Grid>
</ContentView>

背后的代码

namespace MyProject.Views._Controls
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MyButton : ContentView
    {
        #region Property Bindings
        public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(MyButton),
            null, propertyChanged: (bo, o, n) => ((MyButton)bo).OnCommandChanged());

        public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object),
            typeof(MyButton), null,
        propertyChanged: (bindable, oldvalue, newvalue) => ((MyButton)bindable).CommandCanExecuteChanged(bindable, EventArgs.Empty));

        public static readonly new BindableProperty IsEnabledProperty =
            BindableProperty.Create(
                propertyName: "IsEnabled",
                returnType: typeof(Boolean),
                declaringType: typeof(MyButton),
                defaultValue: false,
                defaultBindingMode: BindingMode.OneWay,
                propertyChanged: IsEnabledChanged);

        private static void IsEnabledChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var control = (MyButton)bindable;
            bool enabled = (bool)newValue;
            control.WhenEnabledButton.IsVisible = enabled;
            control.WhenDisabledButton.IsVisible = !enabled;

            if (Device.RuntimePlatform == Device.WinPhone || Device.RuntimePlatform == Device.WinRT)
            {
                control.DisabledButtonCoveringLabel.IsVisible = !enabled;
            }
        }

        public static readonly BindableProperty TextProperty =
            BindableProperty.Create(
                propertyName: "Text",
                returnType: typeof(string),
                declaringType: typeof(MyButton),
                defaultValue: string.Empty,
                defaultBindingMode: BindingMode.OneWay,
                propertyChanged: TextChanged);

        private static void TextChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var control = (MyButton)bindable;
            control.WhenEnabledButton.Text = (string)newValue;
            control.WhenDisabledButton.Text = (string)newValue;
        }

        public static readonly BindableProperty EnabledStyleProperty =
            BindableProperty.Create(
                propertyName: "EnabledStyle",
                returnType: typeof(Style),
                declaringType: typeof(MyButton),
                defaultBindingMode: BindingMode.OneWay,
                propertyChanged: EnabledStyleChanged);

        private static void EnabledStyleChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var control = (MyButton)bindable;
            control.WhenEnabledButton.Style = (Style)newValue;
        }

        public static readonly BindableProperty DisabledStyleProperty =
            BindableProperty.Create(
                propertyName: "DisabledStyle",
                returnType: typeof(Style),
                declaringType: typeof(MyButton),
                defaultBindingMode: BindingMode.OneWay,
                propertyChanged: DisabledStyleChanged);

        private static void DisabledStyleChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var control = (MyButton)bindable;
            control.WhenDisabledButton.Style = (Style)newValue;
        }
        #endregion


        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        public object CommandParameter
        {
            get { return GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }

        public string Text
        {
            get
            {
                return this.GetValue<string>(TextProperty);
            }

            set
            {
                this.SetValue(TextProperty, value);
            }
        }

        public new bool IsEnabled
        {
            get
            {
                return this.GetValue<bool>(IsEnabledProperty);
            }

            set
            {
                this.SetValue(IsEnabledProperty, value);
            }
        }

        #region Click event

        public delegate void ClickedHandler(object sender, EventArgs e);
        public event ClickedHandler Clicked;

        private void WhenEnabledButton_Clicked(object sender, EventArgs e)
        {
            if (Clicked != null)
                this.Clicked.Invoke(sender, e);
            else
                this.Command.Execute(this.CommandParameter);
        }

        void CommandCanExecuteChanged(object sender, EventArgs eventArgs)
        {
            ICommand cmd = Command;
            if (cmd != null)
                IsEnabled = cmd.CanExecute(CommandParameter);
        }

        void OnCommandChanged()
        {
            if (Command != null)
            {
                Command.CanExecuteChanged += CommandCanExecuteChanged;
                CommandCanExecuteChanged(this, EventArgs.Empty);
            }
            else
                IsEnabled = true;
        }

        #endregion

        public MyButton()
        {
            InitializeComponent();
            if (Device.RuntimePlatform == Device.Android)
            {
                DisabledButtonCoveringLabel.IsVisible = false;
                WhenDisabledButton.IsEnabled = false;
            }
            else if (Device.RuntimePlatform == Device.WinPhone || Device.RuntimePlatform == Device.WinRT)
            {
                DisabledButtonCoveringLabel.IsVisible = true;
                WhenDisabledButton.IsEnabled = true;
            }

            this.SetValue(EnabledStyleProperty, Application.Current.Resources["GreenEnabledButtonStyle"]);
            this.SetValue(DisabledStyleProperty, Application.Current.Resources["GreenDisabledButtonStyle"]);
        }
    }
}