【问题标题】:How to access object name in custom classes using Xamarin.forms?如何使用 Xamarin.forms 访问自定义类中的对象名称?
【发布时间】:2017-02-15 17:11:59
【问题描述】:

最近我开始使用 Xamarin.Forms 进行开发。我正在创建一个应用程序,我必须在其中自定义按钮,所以我创建了 customButton 类。现在,我想使用 object.name 属性访问自定义类中的按钮,但我无法做到这一点。谁能建议我如何做到这一点。

代码

<local:CustomButton x:Name="signInButton"  Text="Sign In" Clicked="OnLoginButtonClicked"  TextColor ="White" FontSize="15" FontAttributes="Bold"/>

Android 项目中的CustomButton 类

namespace Sample.Droid
{
    class CustomButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {

                //Want to access button name in if condition, instead of Control.
                //Hope this will help you all in understanding my problem.
            }
        }
    }
}

谢谢

【问题讨论】:

  • 尽量确保将您的自定义类放在 interface 上,并添加对它的引用
  • “使用 object.name 属性访问自定义类中的按钮”是什么意思,您想在自定义渲染器中获取按钮的名称属性吗?例如,如果您在 android 项目中创建自定义 ButtonRenderer,通常我们使用 ID 来标识控件,而不是名称,因此它是特定于平台的,那么您要在哪个平台上获取名称属性?还是只是想获取自定义渲染器类名?
  • 我正在尝试在 Android 和 iOS 平台上使用 x:Name="signInButton" 属性,我有 4 个按钮,我想自定义每个按钮。所以,我正在考虑为此使用 if 或 switch case。但在 CustomButton 类中,我无法根据 name 属性访问我的按钮。
  • 显示您编写的代码将帮助我们所有人首先准确了解您的问题,并更好地帮助您。例如,您是否使用自定义渲染器?您是否尝试从 Android 项目内部访问 PCL 中的对象名称?
  • 我已经添加了代码,虽然格式有点错误。是的,我正在尝试访问 Android 项目中的对象名称。

标签: xamarin.ios xamarin.android xamarin.forms custom-renderer


【解决方案1】:

我无法使用 Element.Text 属性,因为我将删除文本并将图像设置为我的按钮。我需要使用 Tag 或 Name 属性

Name是在Render处理阶段分配的,对于android平台,如我所说,通常我们使用id来标识控件。这里似乎无法公开 name 属性,解决方法是我们可以通过注册BindableProperty 来公开属性。例如:

public class MyButton : Button
{
    public string ButtonName
    {
        get { return (string)GetValue(ButtonNameProperty); }
        set { SetValue(ButtonNameProperty, value); }
    }

    public static readonly BindableProperty ButtonNameProperty =
        BindableProperty.Create(
            propertyName: "ButtonName",
            returnType: typeof(string),
            declaringType: typeof(MyButton),
            defaultValue: null,
            propertyChanged: OnButtonNameChanged);

    private static void OnButtonNameChanged(BindableObject bindable, object oldValue, object newValue)
    {
    }
}

后面的代码:

public class MyButtonRenderer : ButtonRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
    {
        base.OnElementChanged(e);
        //Element.Id

        if (Element != null)
        {
            var element = Element as MyButton;
            var name = element.ButtonName;
        }
    }
}

你代码中的一个小问题是自定义渲染器中的Control表示各个平台的原生控件,Element是你的自定义控件,所以我这里使用了Element属性。

并使用此控件:

<local:MyButton x:Name="signInButton" Text="custom button" ButtonName="signInButton" />

我知道在使用此自定义Button 时设置两次 name 属性很烦人,但这是我目前找到的从渲染器获取每个自定义按钮的标签的唯一方法。如果您不需要在 PCL 的代码中访问此 Button,那么您可能不需要设置 x:Name 属性。

【讨论】:

  • 感谢 Grace 的回答,一切正常。我有一个疑问,我们不能使用 commandParameter 属性而不是创建我们自己的属性。
  • CommandParameter 通常用于Command执行时向Command传递数据,我个人认为在这里使用这个属性不是一个好主意。
【解决方案2】:

首先,我不确定你有没有,你需要在你的命名空间顶部添加这行代码:

[assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]

其次,在您的代码中,您可以访问元素本身,例如:

if (control != null)
{
    string buttonText = Element.Text; //In your posted case it will be equal to "Sign In"
}

我不确定您是否真的可以从 CustomRenderer 内部访问 x:Name 属性,因为它是类变量名。但是根据您要执行的操作,您拥有所有 Element 对象你可以一起工作。

编辑

我找不到直接访问 name 属性的方法,但您可以解决此问题。
在您的 PCL 项目和 CustomButton 类中,您可以添加所需的属性:

public class CustomButton : Button
{
    public string Name { get; set; }
    //rest of your code
}

在您的 xaml 页面中,您现在可以将其添加为属性,例如:

<local:CustomButton x:Name="signInButton" Name="signInButton" Text="Sign In" Clicked="OnLoginButtonClicked"  TextColor ="White" FontSize="15" FontAttributes="Bold"/>

然后在我之前向您展示的渲染器中,您现在可以这样做:

if (Control != null)
{
    string buttonName = ((CustomButton)Element).Name; //it will have the "signInButton" now.
}

【讨论】:

  • OP 要求 name 属性,你给他Text 属性?
  • [assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))] 我的代码中已经有这一行...其次我不能使用 Element.Text 属性,因为我将删除文本并将图像设置为我的按钮。我需要使用 Tag 或 Name 属性...
  • @user3722296 我添加了另一种使用名称的方式
  • 感谢 Paul 的解决方案,我没有尝试过,但我认为这也可以。谢谢。
最近更新 更多