【问题标题】:Xamarin.Forms UserControl using XAML and Custom RendererXamarin.Forms UserControl 使用 XAML 和自定义渲染器
【发布时间】:2014-08-29 03:05:39
【问题描述】:

已经有一些很好的例子来说明如何通过 -

创建“自定义控件”

我想创建一个“复合自定义控件或 usercontrol”,其中包含在 XAML 中定义的多个元素(在共享代码中),然后使用渲染器进行自定义(比如调整样式每个平台)。

请问有人有这样做的例子吗?一个带有可绑定标签和输入框的视图的简单示例应该足以显示主要原理。

这是我目前所拥有的 -

定义了一个 ContentView 来表示我们的用户控件布局和内容。

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="News.Forms.VisualNewsContentView">
    <ContentView.Content>
        <StackLayout>
            <Label x:Name="MyLabel" Text="Label"></Label>
            <Entry x:Name="MyEntry" Text="Entry"></Entry>
        </StackLayout>
    </ContentView.Content>
</ContentView>

使用代码隐藏 -

public partial class VisualNewsContentView : ContentView
{
    public VisualNewsContentView ()
    {
        InitializeComponent ();
    }

    // Not sure if I need this to access Entry ...
    public Entry GetEntry ()
    {
        return MyEntry;
    }
}

为该 ContentView 添加一个 Android 自定义渲染器,我如何访问和自定义 ContentView 的本机部分/控件?

[assembly:ExportRenderer (typeof(VisualNewsContentView), typeof(VisualNewsRenderer))]

namespace News.Forms.Android
{
    public class VisualNewsRenderer: ViewRenderer
    {
        public VisualNewsRenderer () { }

        protected override void OnModelChanged (VisualElement oldModel, VisualElement newModel)
        {
            base.OnModelChanged (oldModel, newModel);

            if (newModel != null) {
                VisualNewsContentView newsContentView = newModel as VisualNewsContentView;

                // i.e. How could I get hold of EditText etc so I could natively customise its appearance? When you use a built in renderer like EntryRenderer you can use Control to access native control.
                Console.WriteLine (newsContentView.GetLabel ().Text);
                EditText ed = (EditText)newsContentView.GetEntry ().???
            }
        }
    }
}

只是无法将这些部分组合在一起工作,ContentView 似乎在页面上渲染得很好,但无法弄清楚如何在 viewrenderer 中访问其 Child Native 控件。

也很高兴展示如何将绑定用于标签和条目文本值。

我不想为用户控件的每个标签/条目等定义自定义渲染器。

【问题讨论】:

    标签: xamarin.forms


    【解决方案1】:

    这是你的意思吗?

    访问 Xamarin.Forms 控件的一些属性:

        public partial class VisualNewsContentView : ContentView
        {
            public VisualNewsContentView()
            {
                InitializeComponent();
            }
    
            public Label Label
            {
                get
                {
                    return MyLabel;
                }
                set
                {
                    MyLabel = value;
                }
            }
    
            public Entry Entry
            {
                get
                {
                    return MyEntry;
                }
                set
                {
                    MyEntry = value;
                }
            }
        }
    

    渲染器内部的一些魔法来自定义页面上的控件:

    [assembly:ExportRenderer (typeof(VisualNewsContentView), typeof(VisualNewsRenderer))]
    
    namespace News.Forms.Android
    {
        public class VisualNewsRenderer: ViewRenderer
        {
            public VisualNewsRenderer () { }
    
            protected override void OnModelChanged (VisualElement oldModel, VisualElement newModel)
            {
                base.OnModelChanged (oldModel, newModel);
    
                if (newModel != null) {
                    VisualNewsContentView newsContentView = newModel as VisualNewsContentView;
                    newsContentView.Label.Text = "It´s some kind of..";
                    newsContentView.Entry.Text = "MAGIC!";
                    newsContentView.Entry.BackgroundColor = Color.Blue;
                    newsContentView.Entry.RotationX = 180;
                    newsContentView.Entry.Focus();
    
                }
            }
        }
    }
    

    编辑:

    我不知道是否可以将您的控件从 XAML 页面映射到本机控件。您可以在渲染器中添加要在本地自定义的控件。

        [assembly:ExportRenderer (typeof(VisualNewsContentView), typeof(VisualNewsRenderer))]
    
    namespace News.Forms.Android
    {
        public class VisualNewsRenderer: NativeRenderer
        {
            public VisualNewsRenderer () { }
    
            protected override void OnModelChanged (VisualElement oldModel, VisualElement newModel)
            {
                base.OnModelChanged (oldModel, newModel);
    
                if (newModel != null) {
                    LinearLayout layout = new LinearLayout (Application.Context);
                    layout.Orientation = Orientation.Vertical;
    
                    TextView tv = new TextView (Application.Context);
                    tv.Ellipsize = TextUtils.TruncateAt.Middle;
                    tv.Text = "It´s some kind of..";
    
                    EditText et = new EditText (Application.Context);
                    et.SetTextColor (Graphics.Color.Chocolate);
                    et.Text = "MAGIC!";
    
                    layout.AddView (tv);
                    layout.AddView (et);
    
                    SetNativeControl (layout);
                }
            }
        }
    }
    

    但是像这样你不会使用你的 ContentView.. 对不起,我没有比这更好的了..

    【讨论】:

    • 嗨@Bart,谢谢你的回答,如果我不清楚,很抱歉,但我需要访问底层的原生 Android 控件/视图(即 EditText),所以我可以做我做不到的原生定制直接使用 Forms 属性。
    • @WickedW 我编辑了我的答案,但我不知道是否可以将表单元素映射到本机元素。
    • 感谢@Bart,看起来它要么在单个控件/视图级别进行自定义,要么接管整个页面/uicontroller 并按照您的建议通过提供或“混合”方法进行自定义。 Xamarin Forms 团队中的某个人是否愿意评论他们是否可以/计划允许我们获取用户控件上的控件以进行自定义?
    • 也许您可以在bugzilla 或他们的论坛上提及它 - xamarin-forms section
    【解决方案2】:

    我自定义复合用户控件的解决方案是为复合用户控件中使用的每个控件制作一个自定义控件。 比如这个控件:

    <ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="News.Forms.VisualNewsContentView">
        <ContentView.Content>
            <StackLayout>
                <Label x:Name="MyLabel" Text="Label"></Label>
                <Entry x:Name="MyEntry" Text="Entry"></Entry>
            </StackLayout>
        </ContentView.Content>
    </ContentView>
    

    我会这样做:

    <ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:CustomControls="clr-namespace:App.CustomControls;assembly=App"  x:Class="News.Forms.VisualNewsContentView">
            <ContentView.Content>
                <CustomControls:StackLayout>
                    <CustomControls:Label x:Name="MyLabel" Text="Label"></CustomControls:Label>
                    <CustomControls:Entry x:Name="MyEntry" Text="Entry"></CustomControls:Entry>
                </CustomControls:StackLayout>
            </ContentView.Content>
        </ContentView>
    

    CustomControls 的示例类:StackLayout 是:

    (在 StackLayout.cs 中)

    using Xamarin.Forms;
    
    namespace App.CustomControls
    {
        public class StackLayout : Xamarin.Forms.StackLayout
        {
        }
    }
    

    (在 Android 项目的 StackLayoutRenderer.cs 中)

    [assembly: ExportRenderer(typeof(App.CustomControls.StackLayout), typeof(App.Droid.CustomRenderers.StackLayoutRenderer))]
    namespace App.Droid.CustomRenderers.MapView
    {
        public class StackLayoutRenderer : ViewRenderer<StackLayout, Android.Widget.LinearLayout>
        {
            protected override void OnElementChanged(ElementChangedEventArgs<StackLayout> e)
            {
                base.OnElementChanged(e);                               
            }           
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-31
      • 2017-01-07
      • 1970-01-01
      • 2021-04-28
      • 2014-09-27
      • 1970-01-01
      • 1970-01-01
      • 2019-11-02
      相关资源
      最近更新 更多