Custom vertices not drawing

In the end, the resulting class ended up like this:

    public sealed class TileRenderer : ITileRenderer
    {
        private const int MaxTextures = 4;

        /*private static readonly Dictionary<Renderer, TileRenderer> RendererDictionary =
            new Dictionary<Renderer, TileRenderer>();*/

        public static Colour ShadowColour;
        private readonly IGraphicsContext _graphicsContext;

        private TileBlendMode _tempLastBlendMode;

        //private readonly List<Vertex> _vertices = new List<Vertex>();
        private const int VerticesArrayLength = 256;
        private static Vertex[] _vertices = new Vertex[VerticesArrayLength];
        public int NumVertices;
        private static readonly Vector2[] VertexPositions = new Vector2[4];
        private static readonly Vector2[] VertexUVs = new Vector2[4];

        private Effect _effect;

        public TileRenderer(ContentManager content, IGraphicsContext graphicsContext)
        {

            _graphicsContext = graphicsContext;

            _effect = content.Load<Effect>("shaders/tile");

            // Set defaults
            ModelMatrix = Matrix4.Identity;
            Colour = Colours.White;
            ClipRectangle = new Rectangle(0, 0, 1920, 1080);
        }

        public Colour Colour { get; set; }

        // Input options
        public Matrix4 ModelMatrix { get; set; }
        public ITexture[] Textures { get; set; }
        public Rectangle ClipRectangle { get; set; }

        public int Filter { get; set; }
        public double FilterAmount { get; set; }

        public bool Rendering { get; private set; }

        public int NumTiles { get; private set; }

        public void Dispose()
        {
        }

        public void Deactivate() { }

        public void BeginRender()
        {
            if(Rendering)
                throw new InvalidOperationException("Already renderering.");
            Rendering = true;

            NumTiles = 0;
            NumVertices = 0;
        }

        public void AddTile(
            Rectanglei source,
            Rectanglei destination,
            int textureIndex,
            bool flipX = false,
            bool flipY = false,
            float opacity = 1.0f,
            TileBlendMode blend = TileBlendMode.Alpha
        )
        {
            if(!Rendering)
                throw new Exception("Not currently renderering");

            var texture = Textures[textureIndex];

        // Add the vertices
        // Renderer.GetVertices(destination, VertexPositions);
        Array.Copy(destination.Vertices, 0, VertexPositions, 0, 4);
            Renderer.GetTextureMappings(texture, source, VertexUVs, flipX, flipY);
            for(var i = 0; i < 4; i++)
            {
                _vertices[NumVertices].VertexPosition.X = (float) VertexPositions[i].X;
                _vertices[NumVertices].VertexPosition.Y = (float) VertexPositions[i].Y;
                _vertices[NumVertices].VertexTextureMapping.X = (float) VertexUVs[i].X;
                _vertices[NumVertices].VertexTextureMapping.Y = (float) VertexUVs[i].Y;
                _vertices[NumVertices].VertexTextureIndex = textureIndex;
                _vertices[NumVertices].VertexOpacity = opacity;

                NumVertices++;

                if(NumVertices >= _vertices.Length)
                {
                    var tempVertex = new Vertex[_vertices.Length + VerticesArrayLength];
                    Array.Copy(_vertices, tempVertex, _vertices.Length);
                    _vertices = tempVertex;
                }
            }

            NumTiles++;

            _tempLastBlendMode = blend;
        }

        public void SetUpEffect()
        {
            var graphicsContext = _graphicsContext;
            var graphics = (graphicsContext as MonoGameGraphicsContext);

            var GraphicsDevice = graphics.WindowContext.Graphics.GraphicsDevice;

            var viewport = GraphicsDevice.Viewport;

            //var World = SimpleRenderer._modelMatrix;

            var ortho = ModelMatrix;
            var World = new Microsoft.Xna.Framework.Matrix(
                new Microsoft.Xna.Framework.Vector4((float)ortho.Row1.X, (float)ortho.Row1.Y, (float)ortho.Row1.Z, (float)ortho.Row1.W),
                new Microsoft.Xna.Framework.Vector4((float)ortho.Row2.X, (float)ortho.Row2.Y, (float)ortho.Row2.Z, (float)ortho.Row2.W),
                new Microsoft.Xna.Framework.Vector4((float)ortho.Row3.X, (float)ortho.Row3.Y, (float)ortho.Row3.Z, (float)ortho.Row3.W),
                new Microsoft.Xna.Framework.Vector4((float)ortho.Row4.X, (float)ortho.Row4.Y, (float)ortho.Row4.Z, (float)ortho.Row4.W));


            var View = Microsoft.Xna.Framework.Matrix.CreateLookAt(new Microsoft.Xna.Framework.Vector3(0, 0, -1), new Microsoft.Xna.Framework.Vector3(0, 0, 0), new Microsoft.Xna.Framework.Vector3(0, -1, 0));
            //var Projection2 = Microsoft.Xna.Framework.Matrix.CreateScale(1, -1, 1) * Microsoft.Xna.Framework.Matrix.CreateOrthographicOffCenter(0, 1920, 1080, 0, 0, 1); // nans

            ortho = _graphicsContext.CurrentFrameBuffer.CreateOrthographic() * Matrix4.CreateScale(1, -1, 1);
            var Projection = new Microsoft.Xna.Framework.Matrix(
                new Microsoft.Xna.Framework.Vector4((float)ortho.Row1.X, (float)ortho.Row1.Y, (float)ortho.Row1.Z, (float)ortho.Row1.W),
                new Microsoft.Xna.Framework.Vector4((float)ortho.Row2.X, (float)ortho.Row2.Y, (float)ortho.Row2.Z, (float)ortho.Row2.W),
                new Microsoft.Xna.Framework.Vector4((float)ortho.Row3.X, (float)ortho.Row3.Y, (float)ortho.Row3.Z, (float)ortho.Row3.W),
                new Microsoft.Xna.Framework.Vector4((float)ortho.Row4.X, (float)ortho.Row4.Y, (float)ortho.Row4.Z, (float)ortho.Row4.W));

            var wvp = World * View * Projection;

            _effect.Parameters["World"].SetValue(World);
            _effect.Parameters["View"].SetValue(View);
            _effect.Parameters["Projection"].SetValue(Projection);

            for (var i = 0; i < Textures.Length; i++)
            {
                var texture = (Textures[i] as MonoGameTexture).Texture;
                _effect.Parameters["InputTexture" + i.ToString()].SetValue(texture);
            }

            _effect.Parameters["AlphaGrayScale"].SetValue(ShadowRenderer.IsShadowing ? 1.0f : 0.0f);

            _effect.Parameters["InputColour"].SetValue(new Microsoft.Xna.Framework.Vector4(Colour.Red / 255.0f, Colour.Green / 255.0f, Colour.Blue / 255.0f, Colour.Alpha / 255.0f));
            _effect.Parameters["ShadowColour"].SetValue(new Microsoft.Xna.Framework.Vector4(ShadowColour.Red / 255.0f, ShadowColour.Green / 255.0f, ShadowColour.Blue / 255.0f, ShadowColour.Alpha / 255.0f));
            _effect.Parameters["InputFilter"].SetValue(Filter);
            _effect.Parameters["InputFilterAmount"].SetValue((float)FilterAmount);

            _effect.Parameters["InputClipRectangle"].SetValue(new Microsoft.Xna.Framework.Vector4((float)ClipRectangle.X, (float)ClipRectangle.Y, (float)ClipRectangle.Right, (float)ClipRectangle.Bottom));

            //_effect.Parameters["FragmentTextureIndex"].SetValue(_vertices[0].VertexTextureIndex);
            //_effect.Parameters["FragmentOpacity"].SetValue(_vertices[0].VertexOpacity);

            _effect.Parameters["InputFilter"].SetValue(Filter);

        }

        private void DrawQuad(Vertex[] destination)
        {
            var graphicsContext = _graphicsContext;
            var graphics = (graphicsContext as MonoGameGraphicsContext);
            var GraphicsDevice = graphics.WindowContext.Graphics.GraphicsDevice;

            Vertex[] quad = destination;

            short[] indices = new short[6];
            if (GraphicsDevice.RasterizerState == RasterizerState.CullClockwise)
            {
                indices[0] = 0; indices[1] = 1; indices[2] = 2;
                indices[3] = 2; indices[4] = 3; indices[5] = 0;
            }
            else
            {
                indices[0] = 0; indices[1] = 2; indices[2] = 1;
                indices[3] = 2; indices[4] = 0; indices[5] = 3;
            }

            foreach (EffectPass pass in _effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                GraphicsDevice.SetVertexBuffer(null);
                GraphicsDevice.DrawUserIndexedPrimitives(Microsoft.Xna.Framework.Graphics.PrimitiveType.TriangleList, quad, 0, 4, indices, 0, 2, Vertex.VertexDeclaration);
            }
        }


        public void SetStates()
        {
            var graphicsContext = _graphicsContext;
            var graphics = (graphicsContext as MonoGameGraphicsContext);

            var GraphicsDevice = graphics.WindowContext.Graphics.GraphicsDevice;

            // Alpha blending
            graphics.BlendMode = _tempLastBlendMode == TileBlendMode.Additive ? BlendMode.Additive : BlendMode.Alpha;
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap;
            GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
        }

        public void EndRender()
        {
            if(!Rendering)
                throw new Exception("Not currently renderering");

            SetStates();

            // Prepare textures
            foreach(var texture in Textures)
                texture.Filtering = TextureFiltering.NearestNeighbour;

            SetUpEffect();
            DrawQuad(_vertices);

            Rendering = false;
        }

        private struct Vertex : IVertexType
        {
            public Microsoft.Xna.Framework.Vector3 VertexPosition;

            public Microsoft.Xna.Framework.Vector2 VertexTextureMapping;

            public float VertexTextureIndex;

            public float VertexOpacity;

            public static int currentByteSize = 0;
            public static int Offset(float n) { var s = sizeof(float); currentByteSize += s; return currentByteSize - s; }
            public static int Offset(Microsoft.Xna.Framework.Vector2 n) { var s = sizeof(float) * 2; currentByteSize += s; return currentByteSize - s; }
            public static int Offset(Microsoft.Xna.Framework.Color n) { var s = sizeof(int); currentByteSize += s; return currentByteSize - s; }
            public static int Offset(Microsoft.Xna.Framework.Vector3 n) { var s = sizeof(float) * 3; currentByteSize += s; return currentByteSize - s; }
            public static int Offset(Microsoft.Xna.Framework.Vector4 n) { var s = sizeof(float) * 4; currentByteSize += s; return currentByteSize - s; }

            public readonly static VertexDeclaration VertexDeclaration =
              new VertexDeclaration(new VertexElement(Offset(Microsoft.Xna.Framework.Vector3.Zero), VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
                                    new VertexElement(Offset(Microsoft.Xna.Framework.Vector2.Zero), VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
                                    new VertexElement(Offset(0.0f), VertexElementFormat.Single, VertexElementUsage.TextureCoordinate, 1),
                                    new VertexElement(Offset(0.0f), VertexElementFormat.Single, VertexElementUsage.TextureCoordinate, 2));
            VertexDeclaration IVertexType.VertexDeclaration
            {
                get { return Vertex.VertexDeclaration; }
            }

        }


    }

It looks like the correct way of specifying positions is with the usage of Vector3 not Vector4, I have some other errors but those are unrelated to drawing.