1

Please consider the following issue.

In my Xamarin.Forms app I have a custom render for UWP that allows for a button to have two lines, and be centralised.

The buttons in questions are items in a Listview that are bound to objects. When they are initially generated, they display correctly with both lines of text in the center of the button, however if I update the text, it updates, but seems to bypass the custom renders "be in the center" code.

Please see the below code snippets and images to explain the situation further.

Custom Render

[assembly: ExportRenderer(typeof(TwoLinedButton), typeof(TwoLinedButtonUWP))]
namespace aphiresawesomeproject.UWP
{
    public class TwoLinedButtonUWP : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            if (Control != null && e.NewElement.Text != null)
            {
                var textBlock = new Windows.UI.Xaml.Controls.TextBlock
                {
                    Text = e.NewElement.Text,
                    TextAlignment = Windows.UI.Xaml.TextAlignment.Center,
                    TextWrapping = TextWrapping.WrapWholeWords
                };
                Control.Content = textBlock;
            }
        }
    }
}

XAML

<ListView x:Name="AphiresListView" CachingStrategy="RecycleElement" ItemsSource="{Binding ListViewItems}" Margin="0,20,0,0" RowHeight="130" SeparatorVisibility="None" VerticalOptions="FillAndExpand" Grid.Column="1" Grid.Row ="3" >
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <local:TwoLinedButton Command="{Binding ClickedCommand}" Margin="5,10,5,10" HorizontalOptions ="FillAndExpand" BackgroundColor="{Binding color_hex}" Grid.Column="1" TextColor="{StaticResource LightTextColor}" FontSize="Medium" Text="{Binding problem_title}"></local:TwoLinedButton>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Update in Viewmodel

foreach (AphiresObject ViewItem in ListViewItems)
{
    ViewItem.problem_title = ViewItem.problem_title.Replace("Line 2", "Updated Line 2");
}

Before

enter image description here

After

enter image description here

Aphire
  • 1,621
  • 25
  • 55

2 Answers2

3

I think all you need to do is override OnElementPropertyChanged in your renderer and set the textBlock properties again when your text property changes.

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);

    if (e.PropertyName == TwoLinedButton.TextProperty.PropertyName)
    {
        //Set text block properties
    }
}
Nick Peppers
  • 3,161
  • 23
  • 27
  • Hey Nick, thanks for your time on this. When I drop that code snippet in I appear not to have access to e.NewElement, so not sure how to set the Text parameter of the Textblock (updated comment as I see you dropped in an edit, thanks!) – Aphire May 04 '18 at 14:13
  • Thanks for the update, i've edited my above comment. Cheers! – Aphire May 04 '18 at 14:21
  • `Control` and `Element` should both be found in `OnElementPropertyChanged` you just might need to check to make sure they're not null – Nick Peppers May 04 '18 at 14:23
  • Perfect, you are a gent. Thanks. – Aphire May 04 '18 at 14:24
0

You may also need to tell the view to re-render itself.

iOS: this.SetNeedsDisplay();

Android: this.Invalidate(); 
biruk1230
  • 3,042
  • 4
  • 16
  • 29
nz-io
  • 1
  • 2