I'm trying to determine why does the following C# code not result in the same output as the XAML version (Top picture is XAML, bottom picture is the code behind). All the parameters have equal values and I've nested my stacklayouts, and I'm not sure what is missing to equate the two outputs. Any help would be much appreciated. Thanks!
The following is the XAML code:
<StackLayout VerticalOptions="StartAndExpand" HorizontalOptions="FillAndExpand" Padding="8" Spacing="12" x:Name="JitPageStackView">
<StackLayout Orientation="Horizontal" Spacing="0">
<StackLayout BackgroundColor="#3d4f7c" WidthRequest="50" HeightRequest="50" VerticalOptions="Start">
</StackLayout>
<StackLayout HorizontalOptions="FillAndExpand" Padding="0" BackgroundColor="White">
<Frame HasShadow="True" CornerRadius="0" BackgroundColor="#ededef" Padding="6">
<Label TextColor="Black" Text="This is text"></Label>
</Frame>
</StackLayout>
</StackLayout>
</StackLayout>
And this is the code behind:
var Description = new StackLayout { HorizontalOptions = LayoutOptions.FillAndExpand, Padding = new Thickness(6, 6, 6, 6), BackgroundColor = Color.White };
var Frame = new Frame { Content = new Label { Text = "This is a long text", TextColor = Color.Black }, BackgroundColor = Color.FromHex("ededef"), CornerRadius = 0 };
Description.Children.Add(Frame);
var Step = new StackLayout {WidthRequest = 50, HeightRequest=50, VerticalOptions=LayoutOptions.Start, BackgroundColor=Color.FromHex("3d4f7c") };
var StepDisplay = new StackLayout { Spacing = 0, Orientation = StackOrientation.Horizontal };
StepDisplay.Children.Add(Step);
StepDisplay.Children.Add(Description);
JitPageStackView.Children.Add(StepDisplay);
In the C# version you are setting the padding to the StackLayout "Description" instead of the Frame
Change this and it should work as the XAML version
var Description = new StackLayout { HorizontalOptions = LayoutOptions.FillAndExpand, BackgroundColor = Color.White };
var Frame = new Frame { Content = new Label { Text = "This is a long text", TextColor = Color.Black }, BackgroundColor = Color.FromHex("ededef"), CornerRadius = 0, Padding = new Thickness(6, 6, 6, 6) };
Description.Children.Add(Frame);
var Step = new StackLayout {WidthRequest = 50, HeightRequest=50, VerticalOptions=LayoutOptions.Start, BackgroundColor=Color.FromHex("3d4f7c") };
var StepDisplay = new StackLayout { Spacing = 0, Orientation = StackOrientation.Horizontal };
StepDisplay.Children.Add(Step);
StepDisplay.Children.Add(Description);
JitPageStackView.Children.Add(StepDisplay);
Hope this helps.-
Related
I'm using Xamarin.Forms. I tried this code but it has not worked; how can I resize the buttons?
<ContentView.Content>
<StackLayout>
<Button Text="1" WidthRequest="50"></Button>
<Button Text="2" WidthRequest="50"></Button>
</StackLayout>
</ContentView.Content>
Thank you.
<StackLayout >
<Button Text="1" WidthRequest="50"
HorizontalOptions="Center"></Button>
<Button Text="2" WidthRequest="50"
HorizontalOptions="Center"></Button>
</StackLayout>
You can use HorizontalOptions attribute to make the width or height be as large as needed to contain the elements within it.
<Button HorizontalOptions="Center" Text="Retry" />
<StackLayout>
<!--I am wider but shorter-->
<Button Text="1" WidthRequest="100" HeightRequest="50"></Button>
<!--I am narrower but longer-->
<Button Text="2" WidthRequest="50" HeightRequest="100"></Button>
<!--I fill the whole width. See also VerticalOptions-->
<Button Text="3" HorizontalOptions="FillAndExpand"></Button>
</StackLayout>
Just Size parent View, for example if it's in a StackLayout, it'll be same size with parent.
<Grid HeightRequest="120" WidthRequest="120" HorizontalOptions="Center">
<Button Text="Hello!" BackgroundColor="Red"/>
</Grid>
It'll be shown 120 x 120,
Because, Button's Default HorizontalOptions is Fill, VerticalOptions is Start. But some Controls like buttons, ignores Height or Width request and prefer to fill parent. Other elements in the same Layout effects button. Just resize parent of button and leave it.
Can you try the below mentioned method:
<StackPanel>
<Button Content = "Button1" Height = "30" Width = "80" Foreground = "Blue" FontSize = "12" Margin = "10"/>
<Button Content = "Button2" Height = "30" Width = "80" Foreground = "Blue" FontSize = "12" Margin = "10"/>
<Button Content = "Button3" Height = "30" Width = "80" Foreground = "Blue" FontSize = "12" Margin = "10"/>
</StackPanel>
I´m trying to create a separator between StackLayouts in a XAML page in Xamarin.Forms and I can do that easily with BoxView.
But when I try to add a border to the BoxView (by adding a Frame) I can´t get it to not curve at the ends.
I have tried all kinds of ways to make this work without luck. I even tried to stretch the BoxView out of the screen (take a look at the latter image) to have the curve off the screen (that would just do fine at this moment even)
Here is just few of of the things I tried out without any luck.
<!--Test 1. -->
<Frame OutlineColor="{DynamicResource CardOutlineColor}" HasShadow="False" Padding="0" VerticalOptions="FillAndExpand">
<BoxView x:Name="boxViewSeparator" HeightRequest="15" WidthRequest="10000" BackgroundColor="{DynamicResource WindowsBackgroundColor}" />
</Frame>
<!--Test 2. -->
<AbsoluteLayout VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<Frame OutlineColor="{DynamicResource CardOutlineColor}" HasShadow="False" Padding="0" VerticalOptions="FillAndExpand">
<BoxView AbsoluteLayout.LayoutBounds="1.0, 1.0, 1.0, 1.0"
Color="#f2f3f3"
AbsoluteLayout.LayoutFlags="All" BackgroundColor="{DynamicResource WindowsBackgroundColor}" />
</Frame>
</AbsoluteLayout>
<!--Test3. -->
<Frame OutlineColor="{DynamicResource CardOutlineColor}" HasShadow="False" Padding="0" VerticalOptions="FillAndExpand">
<ContentView HeightRequest="15" BackgroundColor="{DynamicResource WindowsBackgroundColor}" />
</Frame>
<!--Test 4. -->
<Frame OutlineColor="{DynamicResource CardOutlineColor}" HasShadow="False" Padding="0" VerticalOptions="FillAndExpand">
<ContentView HeightRequest="15" BackgroundColor="{DynamicResource WindowsBackgroundColor}" MinimumWidthRequest="500"/>
</Frame>
I came the closest with this this code
<AbsoluteLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Frame OutlineColor="{DynamicResource CardOutlineColor}" HasShadow="False"
Padding="0" VerticalOptions="FillAndExpand"
AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="1.5, 1.5, 1.2, 1.0">
<BoxView HeightRequest="15" BackgroundColor="{DynamicResource WindowsBackgroundColor}" />
</Frame>
</AbsoluteLayout>
But the result is that I only get the other part of the ViewBox out of the window
Does anybody have any other idea?
Ok I found out how to do this and like everything you know, it´s easy :-)
Just use 3 BoxViews in a StackLayout without padding/spacing.
<StackLayout Orientation ="Vertical" Padding="0" Spacing="0">
<BoxView BackgroundColor="#d6dbdb" HeightRequest="1" VerticalOptions="End" HorizontalOptions="FillAndExpand"/>
<BoxView HeightRequest="15" BackgroundColor="#f2f3f3"/>
<BoxView BackgroundColor="#d6dbdb" HeightRequest="1" VerticalOptions="End" HorizontalOptions="FillAndExpand"/>
</StackLayout>
And the result is the following.
p.s
I would like to see how you would off set the frame off the screen...
I've found more elegant solution(IMHO):
Create custom box view:
public class Border : BoxView
{
public static readonly BindableProperty BorderColorProperty =
BindableProperty.Create(nameof(BorderColor),
typeof(Color),
typeof(Border),
Color.Transparent);
public static readonly BindableProperty BorderWidthProperty =
BindableProperty.Create(nameof(BorderWidth),
typeof(double),
typeof(Border),
0d);
public Color BorderColor
{
get { return (Color)GetValue(BorderColorProperty); }
set { SetValue(BorderColorProperty, value); }
}
public double BorderWidth
{
get { return (double)GetValue(BorderWidthProperty); }
set { SetValue(BorderWidthProperty, value); }
}
}
Implement renderers:
ANDROID
public class BorderRenderer : VisualElementRenderer<BoxView>
{
public BorderRenderer()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
{
base.OnElementChanged(e);
SetWillNotDraw(false);
Invalidate();
}
public override void Draw(Canvas canvas)
{
var border = Element as Border;
base.Draw(canvas);
var paint = new Paint();
paint.StrokeWidth = (float)border.BorderWidth;
paint.SetStyle(Paint.Style.Stroke);
paint.SetARGB(ConvertTo255ScaleColor(border.BorderColor.A), ConvertTo255ScaleColor(border.BorderColor.R), ConvertTo255ScaleColor(border.BorderColor.G), ConvertTo255ScaleColor(border.BorderColor.B));
SetLayerType(Android.Views.LayerType.Software, paint);
var number = (float)border.BorderWidth / 2;
var rectF = new RectF(
number, // left
number, // top
canvas.Width - number, // right
canvas.Height - number // bottom
);
canvas.DrawRoundRect(rectF, 0, 0, paint);
}
private int ConvertTo255ScaleColor(double color)
{
return (int)Math.Ceiling(color * 255);
}
}
iOS
public class BorderRenderer : VisualElementRenderer<BoxView>
{
public BorderRenderer()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
{
base.OnElementChanged(e);
if (Element == null)
return;
Layer.MasksToBounds = true;
Layer.CornerRadius = 0f;
}
public override void Draw(CGRect rect)
{
var border = (Border)Element;
using (var context = UIGraphics.GetCurrentContext())
{
context.SetFillColor(border.Color.ToCGColor());
context.SetStrokeColor(border.BorderColor.ToCGColor());
context.SetLineWidth((float)border.BorderWidth);
var rCorner = Bounds.Inset((int)border.BorderWidth / 2, (int)border.BorderWidth / 2);
var radius = (nfloat)border.CornerRadius;
radius = (nfloat)Math.Max(0, Math.Min(radius, Math.Max(rCorner.Height / 2, rCorner.Width / 2)));
var path = CGPath.FromRoundedRect(rCorner, radius, radius);
context.AddPath(path);
context.DrawPath(CGPathDrawingMode.FillStroke);
}
}
}
Don't forget to add attribute above namespace on each renderer:
[assembly: ExportRenderer(typeof(Border), typeof(BorderRenderer))]
I have a question guys. Im kind new to xaml and, I'm trying to make the 4 buttons i created from my xaml code line up with the labels i have created from my xaml code. now, my first image("Image from my xaml code") thats the image i have when running my xaml code. however, when i try to keep it all into one stack layout it doesn't match up as in my finish image in which ("im trying to achieve image") any pointers in the right direction in what im doing wrong?
<!-- Page -->
<StackLayout
x:Name = "CustomerStackLayout">
<Label
x:Name = "ThisLabel"
Text = "Order #2102"
VerticalOptions= "Start" >
</Label>
<Label
Text = "John Doe"
VerticalOptions ="Start">
</Label>
<Label
Text = "(832)-555-4518"
VerticalOptions ="Start">
</Label>
<Label
Text = "5612 StillWater Dr"
VerticalOptions ="Start">
</Label>
<Label
Text = "Houston, TX 77079"
VerticalOptions ="Start">
</Label>
<Label
Text = "Pickup Time:Mon July 10, 4:30PM"
TextColor = "Yellow"
HorizontalOptions = "Center">
</Label>
<!--AbsoluteLayout.LayoutBounds = "0.975,0.01,100,25-->
<Button
x:Name = "callButton"
Text ="call"
HorizontalOptions = "End"
VerticalOptions = "End"
Clicked = "Handle_Clicked"
BackgroundColor = "Red">
</Button>
<!--AbsoluteLayout.LayoutBounds = "0.975,0.06,100,25"-->
<Button
Text = "text"
x:Name = "textButton"
Clicked = "textButton_Clicked"
BackgroundColor = "Red"
HorizontalOptions = "End"/>
<Button
Text = "map"
HorizontalOptions = "End"
VerticalOptions = "Start"
x:Name = "mapButton"
Clicked="MapsButton_Clicked"
BackgroundColor = "Red"/>
<!--AbsoluteLayout.LayoutBounds = ".7,0.9,104,34"-->
<AbsoluteLayout>
<Button
x:Name = "ImOnItButton"
Text ="Im on it"
Clicked = "ImOnIt_Clicked"
IsVisible = "true"
BackgroundColor = "Red"
AbsoluteLayout.LayoutBounds = ".7,0.9,104,34"/>
<!--AbsoluteLayout.LayoutBounds = ".7,0.9,104,34"-->
<Button
x:Name = "ArrivedButton"
Text = "Arrived"
Clicked ="arrivedButton_Clicked"
IsVisible = "false"
BackgroundColor = "Red"
AbsoluteLayout.LayoutBounds = ".7,0.9,104,34"
/>
</AbsoluteLayout>
</StackLayout>
StackLayout will lay out its children in order, either vertically or horizontally. Since you didn't specify an Orientation, Vertical is implied, which is exactly what you are seeing. As the name implies, the children are stacked on top of each other.
The short answer is that you will need a more complex layout than a single StackLayout. You could probably achieve your goal with nested StackLayouts, but that would be tough, and less efficient than other options.
At least for the top portion of your design, a Grid is probably your best bet, something like:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label
x:Name = "ThisLabel"
Text = "Order #2102"
HorizontalOptions = "Center"
Grid.Row = "0"
Grid.Column = "0"
Grid.ColumnSpan = "2">
</Label>
<Label
x:Name = "ThisLabel"
Text = "Order #2102"
VerticalOptions= "Start"
Grid.Row="1"
Grid.Column="0">
</Label>
<Button
x:Name = "callButton"
Text ="call"
HorizontalOptions = "End"
VerticalOptions = "End"
Clicked = "Handle_Clicked"
BackgroundColor = "Red"
Grid.Row="1"
Grid.Column="">
</Button>
<Label
x:Name = "ThisLabel"
Text = "Order #2102"
VerticalOptions= "Start"
Grid.Row="2"
Grid.Column="0">
</Label>
<Button
Text = "text"
x:Name = "textButton"
Clicked = "textButton_Clicked"
BackgroundColor = "Red"
HorizontalOptions = "End"
Grid.Row="2"
Grid.Column="1">
</Button>
<Label
x:Name = "ThisLabel"
Text = "Order #2102"
VerticalOptions= "Start"
Grid.Row="3"
Grid.Column="0">
</Label>
<Button
Text = "map"
HorizontalOptions = "End"
VerticalOptions = "Start"
x:Name = "mapButton"
Clicked="MapsButton_Clicked"
BackgroundColor = "Red"
Grid.Row="3"
Grid.Column="1">
</Button>
</Grid>
You may not need all of the the VerticalOptions and HorizontalOptions with the Grid, but this should be a decent place to start.
I am working on windows phone 7.
i have to bind the images selected from PhotoChooserTask in a ListBox like Tiles in Windows Phone 7.
I have a design file like this:
<ListBox x:Name="lstImages" Height="530" Margin="0,10,0,0"
ScrollViewer.VerticalScrollBarVisibility="Hidden">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Style="{StaticResource PickerBoxButton}"
x:Name="btnDashboardItems"
Tag="{Binding Name}"
Padding="0" Margin="-18,0,-12,-45" Height="200"
Width="200">
<Button.Template>
<ControlTemplate>
<StackPanel Height="173" Width="173">
<Image Height="173" Width="173"
Source="{Binding Image}" />
</StackPanel>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Width="450" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
and i have a class called ImageList like this:
public class ImageList
{
public string Name { get; set; }
public BitmapImage Image { get; set; }
}
and I am binding to the listbox like this:
PhotoChooserTask task = new PhotoChooserTask();
task.Completed += new EventHandler<PhotoResult>(task_Completed);
task.Show();
Here i can select any No of Images So i have taken the ListBox.
Random _Random = new Random();
private void task_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
System.IO.Stream stream = e.ChosenPhoto;
BitmapImage bmp = new BitmapImage();
bmp.CreateOptions = BitmapCreateOptions.None;
bmp.SetSource(stream);
img.Image = bmp;
img.Name = _Random.Next(int.MaxValue).ToString() + ".jpg";
StateUtilities.ImageList.Add(img);
if (StateUtilities.ImageList != null)
{
if (StateUtilities.ImageList.Count > 0)
{
lstImages.ItemsSource = StateUtilities.ImageList;
}
}
}
}
Here i am able bind the images but images are coming at different sizes but i have given fixed size(Height and Width) to button and Image Tag, still I am getting the images in Different Sizes (Different Height and Width) .
How can i make that images bind at Same Size?
Thanks,
Avinash
I think that the StackPanel will stretch according to the content.
Have you tried setting MaxWidth and MaxHeight too?
I'm using a progress bar in my app, this progress bar is defined inside the user control, e.g.:
UserControl x:Class="StirLibrary.ProgressBarControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="480">
<Grid x:Name="LayoutRoot" Height="800">
<Border BorderThickness="2" BorderBrush="Transparent" Background="Transparent" Margin="50,522,50,158">
<StackPanel>
<TextBlock Text="Loading..." Name="loading" Grid.Row="1" HorizontalAlignment="Center" Height="30" Foreground="Green">
</TextBlock>
<ProgressBar Background="Transparent" Margin="10, 0, 0, 10" Height="80" HorizontalAlignment="Center" Name="progressBar1" VerticalAlignment="Top" Width="380" Grid.Row="2" HorizontalContentAlignment="Left" IsHitTestVisible="True" VerticalContentAlignment="Top" Value="0" Maximum="100">
</ProgressBar>
</StackPanel>
</Border>
</Grid>
</UserControl>
My problem is when the orientation of my app changes to landscape the progress bar's orientation doesn't change and this makes the app look ugly. Any suggestions how to avoid this and make the progress bar displayed as per orientation are welcome.
As Matt has mentioned above it is not possible to orient a pop up in user control because User control doesn't have any room for supported orientation. but since it was very crucial requirement for our App i found a work around and made few changes in the Main Page's class file and the user control's class file.. the changes are:
private void PhoneApplicationPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
{
if ((e.Orientation & PageOrientation.Portrait) == PageOrientation.Portrait)
{
ProgressBarControl.getInstance().ProgressBarControl_LayoutUpdated(this, e,e.Orientation.ToString());
}
else if ((e.Orientation & PageOrientation.Landscape) == PageOrientation.Landscape)
{
ProgressBarControl.getInstance().ProgressBarControl_LayoutUpdated(this, e, e.Orientation.ToString());
}
}
These are the changes in MainPage.xaml.cs
public partial class ProgressBarControl : UserControl
{
private static ProgressBarControl instance = null;
public static Popup popup;
private ProgressBarControl()
{
InitializeComponent();
}
public static ProgressBarControl getInstance()
{
if (instance == null)
{
instance = new ProgressBarControl();
popup = new Popup();
popup.Child = instance;
popup.IsOpen = false;
}
return instance;
}
public void ProgressBarControl_LayoutUpdated(object sender, EventArgs e,string orientation)
{
if (orientation == "LandscapeRight")
{
ProgressPanel.RenderTransformOrigin = new Point(0.5, 0.5);
ProgressPanel.RenderTransform = new CompositeTransform { Rotation = 270 };
}
else if(orientation == "LandscapeLeft")
{
ProgressPanel.RenderTransformOrigin = new Point(0.5, 0.5);
ProgressPanel.RenderTransform = new CompositeTransform { Rotation = 90 };
}
else
{
ProgressPanel.RenderTransformOrigin = new Point(0, 0);
ProgressPanel.RenderTransform = new CompositeTransform { Rotation = 0 };
}
}
public static void displayProgressBar(int requestId, int status, string msg)
{
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
if (instance == null)
{
instance = new ProgressBarControl();
popup = new Popup();
popup.Child = instance;
}
popup.IsOpen = true;
instance.loading.Text = msg;
instance.progressBar1.IsIndeterminate = true;
instance.progressBar1.Value = status;
});
}
public static void dismissProgressBar()
{
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
if(popup!=null)
{
popup.IsOpen = false;
}
});
}
}
and this what i have done in my ProgressBarControl.cs file (this is the user control's class file)
Xaml file:
<UserControl x:Class="StirLibrary.ProgressBarControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="480">
<Grid x:Name="LayoutRoot" Height="800">
<!--<Border BorderThickness="2" BorderBrush="Black" Background="Transparent" Margin="54,406,50,320"></Border>-->
<StackPanel x:Name="ProgressPanel" Background="Black" Margin="54,406,50,320">
<TextBlock Text="Loading..." Name="loading" Grid.Row="1" HorizontalAlignment="Center" Height="32" Foreground="White"></TextBlock>
<ProgressBar Background="Green" Margin="10, 0, 0, 10" Height="33" Foreground="White" HorizontalAlignment="Center" Name="progressBar1" VerticalAlignment="Top" Width="351" Grid.Row="2" HorizontalContentAlignment="Left" IsHitTestVisible="True" VerticalContentAlignment="Top" Value="0" Maximum="100"></ProgressBar>
</StackPanel>
</Grid>
</UserControl>
I could enable the orientation for my popup UserControl by simply adding to the Children of the main screen on top of which the Popup is being displayed as:
popUp = new Popup();
loginControl = new LoginPopup(); // this is the custom UserControl
popUp.Child = loginControl;
LayoutRoot.Children.Add(popUp);
The Popup class does not support orientation so you can't use this and expect it to handle orientation changes. This is regardless of whether the control displayed in the popup is in the same assembly or not.
Instead of using a Popup a simple alternative would be to put the control directly on top of all other content on the page. You could include this inside another control (such as a grid or a panel) if you wish.
Manually adding a RotateTransform to the control will give you the ability to add extra control over adjusting the orientation but I'd recommend not going down this route if you can avoid it.