1
votes

I am trying to do something i thought would be simple but i havent been able to find the solution yet. I have a pretty basic custom element for adding a thick border within a frame.

XAML

<?xml version="1.0" encoding="UTF-8" ?>
<Frame
    x:Class="ResumeApp.CustomElements.BetterFrame"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Name="OuterFrame"
    HorizontalOptions="FillAndExpand"
    OutlineColor="Black">
    <Frame
        x:Name="InnerFrame"
        HorizontalOptions="FillAndExpand"
        OutlineColor="Black" />
</Frame>

CodeBehind

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace ResumeApp.CustomElements
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    [ContentProperty(nameof(Content))]
    public partial class BetterFrame : Frame
    {
        private int _Thickness = 0;

        public int Thickness
        {
            get { return _Thickness; }
            set
            {
                Padding = new Thickness(value); _Thickness = value;
            }
        }

        public float Corner
        {
            get { return InnerFrame.CornerRadius; }
            set
            {
                InnerFrame.CornerRadius = value; OuterFrame.CornerRadius = value;
            }
        }

        public new View Content
        {
            get
            {
//Breakpoint not hit here
                return (View)GetValue(ContentProperty);
            }
            set
            {
//breakpoint not hit here
                SetValue(ContentProperty, value);
            }
        }

        public Color InnerColor { get { return InnerFrame.BackgroundColor; } set { InnerFrame.BackgroundColor = value; } }
        public Color OuterColor { get { return OuterFrame.BackgroundColor; } set { OuterFrame.BackgroundColor = value; } }
        public new Color BorderColor { get { return InnerFrame.BorderColor; } set { InnerFrame.BorderColor = value; OuterFrame.BorderColor = value; } }

        public BetterFrame()
        {
            InitializeComponent();
        }

        protected override void OnParentSet()
        {
            base.OnParentSet();

            for (Element Parent = this.Parent; Parent != null; Parent = Parent.Parent)
            {
                try
                {
                    Color background = Parent.GetPropertyIfSet<Color>(BackgroundColorProperty, Color.Transparent);
                    if (background != Color.Transparent && InnerFrame.BackgroundColor != Color.Transparent)
                    {
                        InnerFrame.BackgroundColor = background;
                        break;
                    }
                }
                catch
                {
                }
            }
        }
    }
}

So using the code above when there is no content inside the frame everything looks as expected but once i add content it overwrites the InnerFrame . is there any way of making it so that when i add Content i add it to the InnerFrame instead of the Outter Frame. I added the Content Property to try and catch it being set but i never hit breakpoints set on it so i dont think it is being used.

1
Content is actually set from BindableProperty, so breakpoint will never hit, you have to override OnPropertyChanged and compare name to "Content". - Akash Kava

1 Answers

2
votes

If adding conetent in another Xaml , it will override the inner Frame . Becasue added content is a child view for outer Frame , and Fram only can own one child view . So the inner Frame will be override .

<local:BetterFrame>
    <StackLayout BackgroundColor="AliceBlue">
        <Entry x:Name="myentry2"
                Text="Second Entry" />
    </StackLayout>
</local:BetterFrame>

Here will not show the inner Frame :

enter image description here

Therefore , if adding Content in BetterFrame directly , it will show .

<?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:d="http://xamarin.com/schemas/2014/forms/design"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       mc:Ignorable="d"
       x:Name="OuterFrame"
       x:Class="AppEntryTest.BetterFrame"
       HorizontalOptions="FillAndExpand"
       OutlineColor="Black">
    <Frame x:Name="InnerFrame"
           HorizontalOptions="FillAndExpand"
           OutlineColor="Black">
        <StackLayout BackgroundColor="AliceBlue">
            <Entry x:Name="myentry2"
                   Text="Second Entry" />
        </StackLayout>
    </Frame>
</Frame>

The effect :

enter image description here

=============================Update================================

Create a custom ContentView and contain Outer Frame and Ineer Frame :

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="AppEntryTest.Controls.CustomFrameView">
  <ContentView.ControlTemplate>
        <ControlTemplate >
            <Frame x:Name="FrameExtContainer"
                   Padding="5"
                   HasShadow="False"
                   HorizontalOptions="FillAndExpand"
                   CornerRadius="5"
                   OutlineColor="Black"
                   BorderColor="Black">
                <Frame x:Name="FrameIntContainer"
                       Padding="15"
                       Margin="12"
                       HasShadow="False"
                       HorizontalOptions="FillAndExpand"
                       CornerRadius="5"
                       OutlineColor="Black"
                       BorderColor="Black">
                    <ContentPresenter />
                </Frame>
            </Frame>
        </ControlTemplate>
    </ContentView.ControlTemplate>
</ContentView>

Now used in another Xaml can work:

<local:CustomFrameView>
    <StackLayout BackgroundColor="AliceBlue">
        <Entry x:Name="myentry3"
                Text="Third Entry" />
    </StackLayout>
</local:CustomFrameView>

The effect :

enter image description here