Pregunta

Is there a simple format provider that will return a Rect structure ToString and limit the number of decimal places?

System.Windows.Rect myRect;

If I use myRect.ToString(), it returns

myRect: 0.0139211136847734,0.109375,0.995359599590302,1

I want this, limiting numbers to two decimal places but myRect.ToString("D2") does not compile

 myRect: 0.01,0.10,0.99,1

Note: I don't care about rounding, rounded or truncated is fine.

¿Fue útil?

Solución

You could create an extension method:

public static class RectExtensions
{
    public static string ToStringRounded(this System.Windows.Rect rect)
    {
        return string.Format("{0},{1},{2},{3}", 
            Math.Round(rect.X, 2), Math.Round(rect.Y, 2), 
            Math.Round(rect.Width, 2), Math.Round(rect.Height, 2));
    }
}

and then call myRect.ToStringRounded();

Don't forget to include the namespace of the extension method

Otros consejos

One possible solution would be to implement your own custom format provider, so that you can use the standard ToString method of the rect object. In order to do this, you need to define a custom formatter class that implements the IFormatProvider interface and the ICustomFormatter interface. This ways you could implement your own ToString("D2") solution. An example solution of the custom formatter for your needs can look like this:

public class CustomRectFormat : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        if (formatType == typeof(ICustomFormatter))
        {
            return this;
        }
        else
        {
            return null;
        }
    }

    // the custom format
    public string Format(string fmt, object arg, IFormatProvider formatProvider) 
    {
        // the method processes every part of the Rect members
        var chunk = arg.ToString();
        // skip delimiters
        if (chunk != ";")
        {
            // round doubles if possible
            Double part = 0.0;
            if (Double.TryParse(chunk, out part))
            {
                return Math.Round(part, 2).ToString();
            }
        }
        return chunk;
    }
}

Usage with the standard Rect.ToString method:

var rect = new Rect();
rect.X = 0.5678;
rect.Width = 1.2345;
Console.WriteLine(rect.ToString(new CustomRectFormat()));

The output is as desired:

0,57;0;1,23;0 

Another possible solution would be to implement your own Rect wrapper class. Since Rect is sealed, it can't be subclassed, but you can still create class that mimics the original class. In this class you can overwrite the ToString method with rounding:

public class CustomRect
{
    private Rect rect;

    public CustomRect() : this(new Size(0.0, 0.0))
    {
    }

    public CustomRect(Size size)
    {
        rect = new Rect(size);
    }

    public Double Width
    {
        get { return rect.Width; }
        set { rect.Width = value; }
    }

    public Double X
    {
        get { return rect.X; }
        set { rect.X = value; }
    }

    public Double Y
    {
        get { return rect.Y; }
        set { rect.Y = value; }
    }

    public Double Height
    {
        get { return rect.Height; }
        set { rect.Height = value; }
    }

    public String ToString()
    {
        return String.Format("{0};{1};{2};{3}", Math.Round(rect.X, 2), Math.Round(rect.Y, 2), Math.Round(rect.Width, 2), Math.Round(rect.Height));
    }
}

Usage of the class:

var rect1 = new CustomRect();
var rect2 = new Rect();
rect1.X = 0.123;
rect1.Width = 3.2342342342342;
rect1.Height = 0.987234876234;
rect2.X = 0.123;
rect2.Width = 3.2342342342342;
rect2.Height = 0.987234876234;
Console.WriteLine(rect1.ToString());
Console.WriteLine(rect2.ToString());

And the output is:

0,12;0;3,23;1
0,123;0;3,2342342342342;0,987234876234

This solution has the problem, that you need to use everywhere the custom class and not the predefined Rect class.


Another good approach would be to create (as suggested by @Flat Eric) an extension method that does this for all objects of the Rect class. The downside of this approach is, that you can't use the ToString method when needed.

You need to decide which solution is more suitable for you in this case.

This might have been a more recent development, I don't know, but as of today, this works flawlessly:

$"rect={rect:F2}"

Of course, the older String.Format approach would do the same.

String.Format("{0:F2}", rect);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top