【问题标题】:Can I set multiple properties on a template at the same time with one parameter?我可以使用一个参数同时在模板上设置多个属性吗?
【发布时间】:2018-07-30 05:36:34
【问题描述】:

我有这个模板:

<?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 将是蓝色

边框颜色为灰色

TextColor 将是白色

或者:

<template:button enabled="false">

BackgroundColor 将是白色

边框颜色为黑色

TextColor 将为灰色

【问题讨论】:

    标签: xamarin xamarin.forms


    【解决方案1】:

    所以基本上,您正在尝试创建一个可重用的控件。

    最简单的做法是在代码隐藏中为此添加一个Enabled 属性。这也允许您从 XAML 进行设置。

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

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

    看到您已经有了数据绑定,您应该能够从 setter 更新您绑定到的属性。

    如果您还希望能够绑定到新的Enabled 属性,则必须将其创建为BindableProperty (docs)。添加这个:

    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 property changed 方法,您可以在其中设置颜色的属性。通过这样实现,您还可以绑定到Enabled 属性:&lt;template:button enabled="{Binding IsValid}"&gt;

    编辑:

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

    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 中的保留关键字。你可能想改变它。

    【讨论】:

    • 抱歉,我认为我的问题不清楚,因为您的回答对我没有帮助。我在问题中添加了一些内容。你能看看吗。谢谢
    • 更新到你的“新”问题:)
    • 感谢您的回答。最后一个问题。我一直在使用这个: public bool Enabled { get { return (bool)GetValue(EnabledProperty); } set { SetValue(EnabledProperty, value);但是你没有在你的答案中使用它。你的答案和我做的方式一样吗?
    • 您还可以给我一个示例,说明如何在 OnEnabledChanged 中设置多个颜色属性。谢谢
    • 是的,SetValue 等。INotifyPropertyChanged 也应该使用,导致 UI 自动更新,所以不用担心。您可以像在该方法中通常那样设置属性。
    【解决方案2】:

    对于这个特定的用例,建议使用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); }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2015-09-01
      • 2018-04-04
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-19
      • 1970-01-01
      相关资源
      最近更新 更多