我可以使用一个参数同时在模板上设置多个属性吗?

时间:2018-07-30 05:36:35

标签: xamarin xamarin.forms

我有这个模板:

<?xml version="1.0" encoding="utf-8"?>
<Frame xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
       xmlns:local="clr-namespace:Japanese;assembly=Japanese" 
       x:Class="Japanese.Templates.ButtonTemplate" 
       x:Name="this" CornerRadius="5" 
       BackgroundColor="{Binding FrameBackgroundColor, Source={x:Reference this}}"
       BorderColor="{Binding FrameBorderColor, Source={x:Reference this}}"
       HorizontalOptions="FillAndExpand" HasShadow="false" 
       HeightRequest="35" Padding="0">
    <StackLayout Orientation="Horizontal" Padding="10,5" HorizontalOptions="FillAndExpand">
        <Label Text="{Binding Text,  Source={x:Reference this}}" FontSize="16" 
               TextColor="{Binding LabelTextColor, Source={x:Reference this}}"
               x:Name="label1"
               HorizontalOptions="CenterAndExpand"
               VerticalOptions="Center" HorizontalTextAlignment="Center" />
        <Frame.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding TapButtonPressed, Source={x:Reference this}}" CommandParameter="{Binding Param, Source={x:Reference this}}" NumberOfTapsRequired="1" />
        </Frame.GestureRecognizers>
    </StackLayout>
</Frame>

和此支持CS:

public partial class ButtonTemplate : Frame
{
    public event EventHandler Action;

    public ButtonTemplate()
    {
        InitializeComponent();
    }

    public ICommand TapButtonPressed
    {
        get
        {
            return new Command((object componentIdentifier) =>
            {
                this.Action?.Invoke(this, new EventArgs());
            });
         }
     }

     public static readonly BindableProperty EnabledProperty =
            BindableProperty.Create(
                nameof(Enabled),
                typeof(bool),
                typeof(ButtonTemplate),
                default(bool));
                        
     public bool Enabled { get; set; }

     public static readonly BindableProperty FrameBackgroundColorProperty =
            BindableProperty.Create(
                nameof(FrameBackgroundColor),
                typeof(Color),
                typeof(ButtonTemplate),
                default(Color));
        
     public static readonly BindableProperty FrameBorderColorProperty =
            BindableProperty.Create(
                nameof(FrameBorderColor),
                typeof(Color),
                typeof(ButtonTemplate),
                default(Color));
        
     public static readonly BindableProperty ParamProperty =
            BindableProperty.Create(
                nameof(Param),
                typeof(string),
                typeof(ButtonTemplate),
                default(string));
        
     public static readonly BindableProperty LabelTextColorProperty =
            BindableProperty.Create(
                nameof(LabelTextColor),
                typeof(Color),
                typeof(ButtonTemplate),
                default(Color));
        
     public static readonly BindableProperty TextProperty =
            BindableProperty.Create(
                nameof(Text),
                typeof(string),
                typeof(ButtonTemplate),
                default(string));
        
     public Color FrameBackgroundColor
     {
         get { return (Color)GetValue(FrameBackgroundColorProperty); }
         set { SetValue(FrameBackgroundColorProperty, value); }
     }

     public Color FrameBorderColor
     {
         get { return (Color)GetValue(FrameBorderColorProperty); }
         set { SetValue(FrameBorderColorProperty, value); }
     }

     public Color LabelTextColor
     {
         get { return (Color)GetValue(LabelTextColorProperty); }
         set { SetValue(LabelTextColorProperty, value); }
     }

     public string Param
     {
         get { return (string)GetValue(ParamProperty); }
         set { SetValue(ParamProperty, value); }
     }

     public string Text
     {
         get { return (string)GetValue(TextProperty); }
         set { SetValue(TextProperty, value); }
     }
 }

当前,我使用绑定来设置TextColor,BorderColor和BackgroundColor。但是我需要的是启用和禁用两种状态。是否可以通过一个绑定参数同时将三个绑定值全部设置为一个或其他颜色集?

编辑:

所以我需要的只是一个参数,例如:

<template:button enabled="true">

BackgroundColor将为蓝色

BorderColor将为灰色

TextColor将为白色

或者:

<template:button enabled="false">

BackgroundColor将为白色

BorderColor将为黑色

TextColor将为灰色

2 个答案:

答案 0 :(得分:3)

因此,基本上,您正在尝试创建可重用的控件。

最简单的方法是在后面的代码中添加一个Enabled属性。这也允许您从XAML进行设置。

只需添加:public bool Enabled { get; set; }

然后,您可以在设置器中,通过名称引用模板中的控件,并设置类似的属性。您必须为每个控件添加一个x:Key属性。

看到已经有了数据绑定,您应该能够只从设置器中更新要绑定到的属性。

如果还希望能够绑定到新的Enabled属性,则必须将其创建为BindablePropertydocs)。添加此内容:

public static readonly BindableProperty EnabledProperty =
  BindableProperty.Create (nameof(Enabled), typeof(bool), typeof(ButtonTemplate), null, propertyChanged: OnEnabledChanged);

public bool Enabled { get; set; }

private static void OnEnabledChanged (BindableObject bindable, object oldValue, object newValue)
{
  // Set the color properties here
}

BindableProperty具有on属性更改方法,您可以在其中设置颜色的属性。通过这样实现,您还可以绑定到Enabled属性:<template:button enabled="{Binding IsValid}">

编辑:

设置属性的意思是这样。但是从您的新代码中,我看到您这里没有数据绑定。您确实已经命名了控件,所以您可以引用它们并设置它们的属性,如下所示:

private static void OnEnabledChanged (BindableObject bindable, object oldValue, object newValue)
{
    // Referencing controls
    if ((bool)newValue)
    {
        BorderColor = Color.Red;
        label1.BackgroundColor = Color.Red;
    }
    else
    {
        BorderColor = Color.Green;
        label1.BackgroundColor = Color.Green;
    }

    // Using bindings
    if ((bool)newValue)
    {
        FrameBackgroundColor = Color.Red;
        FrameBorderColor = Color.Red;
    }
    else
    {
        FrameBackgroundColor = Color.Green;
        FrameBorderColor = Color.Green;
    }
}

我看到您已经命名了Frame this。由于this是.NET中的保留关键字,因此可能会引起问题。您可能要更改它。

答案 1 :(得分:1)

对于此特定用例,建议使用VisualStateManager

例如

<Frame xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SampleApp.ButtonView"
             x:Name="this"
             HorizontalOptions="FillAndExpand"
             CornerRadius="5"
             HasShadow="false" 
             HeightRequest="35" Padding="0">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">
            <VisualState x:Name="Normal">
                <VisualState.Setters>
                    <Setter Property="BackgroundColor" Value="Blue" />
                    <Setter Property="BorderColor" Value="Gray" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="Focused" />
            <VisualState x:Name="Disabled">
                <VisualState.Setters>
                    <Setter Property="BackgroundColor" Value="White" />
                    <Setter Property="BorderColor" Value="Black" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <StackLayout Orientation="Horizontal" Padding="10,5" HorizontalOptions="FillAndExpand">
        <Label Text="{Binding Text, Source={x:Reference this}}"
               IsEnabled="{Binding IsEnabled, Source={x:Reference this}}"
               FontSize="16" 
               HorizontalOptions="CenterAndExpand"
               VerticalOptions="Center" HorizontalTextAlignment="Center">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal">
                        <VisualState.Setters>
                            <Setter Property="TextColor" Value="White" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="Focused" />
                    <VisualState x:Name="Disabled">
                        <VisualState.Setters>
                            <Setter Property="TextColor" Value="Gray" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
        </Label>
        <Frame.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding TapButtonPressed,Source={x:Reference this}}" 
                                  CommandParameter="{Binding Param, Source={x:Reference this}}" NumberOfTapsRequired="1" />
        </Frame.GestureRecognizers>
    </StackLayout>
</Frame>

后面的代码:

public partial class ButtonView : Frame
{
    public ButtonView()
    {
        InitializeComponent();

        VisualStateManager.GoToState(this, "Normal");
    }

    public static readonly BindableProperty TextProperty =
        BindableProperty.Create(
            "Text", typeof(string), typeof(ButtonView),
            defaultValue: default(string));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

}