-1

Here's what I'm trying to do:

XAML:

<local:MegaGrid MegaCol="auto,auto,*,auto">
    <Button Grid.Column="0" Content="Btn1"/>
    <Button Grid.Column="1" Content="Btn2"/>
    <Button Grid.Column="2" Content="Btn3 Stretch"    
                            HorizontalAlignment="Stretch"/>
    <Button Grid.Column="3" Content="Btn2"/>
</local:MegaGrid>

C#:

//All the Normal using statements plus a few more...
using System.Text.RegularExpressions;

//Uncomment these two for WPF or comment out for UWP
//using System.Windows;
//using System.Windows.Controls;

namespace NameSpaceOfYourApp {
public class MegaGrid : Grid
{
    private string zMegaRow = "";

    public string MegaRow
    {
        get { return zMegaRow; }
        set
        {
            zMegaRow = value;
            RowDefinitions.Clear();

            string value2 = Regex.Replace(value, @"\s+", "");
            string[] items = value2.Split(',');

            foreach (string item in items)
            {
                // QUESTION: HOW TO CONVERT ITEM
                // DIRECTLY FROM STRING INTO RowDefinition?
                // Without Parsing the string
                if (item == "*")
                {
                    RowDefinitions.Add(
                      new RowDefinition { 
                        Height = new GridLength(1, GridUnitType.Star) }
                    );
                }

                else if (item == "auto")
                {
                    RowDefinitions.Add(
                       new RowDefinition { Height = GridLength.Auto }
                    );
                }
            }
        }
    } // MegaRow

    private string zMegaCol = "";

    public string MegaCol
    {
        get { return zMegaCol; }
        set
        {
            zMegaRow = value;
            ColumnDefinitions.Clear();

            string value2 = Regex.Replace(value, @"\s+", "");
            string[] items = value2.Split(',');

            foreach (string item in items)
            {
                // QUESTION: HOW TO CONVERT ITEM
                // DIRECTLY FROM STRING INTO ColumnDefinition?
                // Without Parsing the string
                if (item == "*")
                {
                    ColumnDefinitions.Add(
                      new ColumnDefinition { 
                        Width = new GridLength(1, GridUnitType.Star) }
                    );
                }

                else if (item == "auto")
                {
                    ColumnDefinitions.Add(
                       new ColumnDefinition { Width = GridLength.Auto }
                    );
                }
            }
        }
    } // MegaCol

} //MegaGrid
} //NameSpaceOfYourApp

What I need to know, is how to call the same String to RowDefinitions converter that the XAML uses to create the RowDefintions object. And the same for ColumnDefinitions. Except to invoke it from C# instead of from XAML. I can easily write if else statements and regex to parse the strings that XAML will accept for RowDefinition and ColumnDefinitions. I was just trying to use the functionals already built into Grid component that XAML invokes when converting from a string into these objects.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Bimo
  • 5,987
  • 2
  • 39
  • 61
  • sorry...just fixed it ... its a property – Bimo Mar 04 '18 at 22:45
  • Look for DependencyProperty – Sir Rufo Mar 04 '18 at 22:45
  • I'm using a regular property because i don't need {binding xxx} for "MegaRow" property... I can just set in from XAML to a constant string... is DependencyProperty the way you convert String in to RowDefinition? – Bimo Mar 04 '18 at 22:47
  • 3
    Side note: it's better to use attached property for this type of thing, not creating custom Grid. – Evk Mar 05 '18 at 04:51

2 Answers2

1

XAML uses TypeConverters to convert to and from strings. You can get the TypeConverter for GridLength (or any other type) like this:

var converter = TypeDescriptor.GetConverter(typeof(GridLength));

Then you can use the TypeConverter.ConvertFromString method in your foreach loop like this:

foreach (string item in items)
{
    ColumnDefinitions.Add(
        new ColumnDefinition { 
            Width = (GridLength)converter.ConvertFromString(item)
        }
    );
}

The above is for your columns, code for the rows would look the same.

Dave M
  • 2,863
  • 1
  • 22
  • 17
  • Just what I was looking for! Thanks. – Bimo Mar 05 '18 at 12:00
  • Also, Needed to add: GridLengthConverter converter = new GridLengthConverter(); ... Width = (GridLength)converter.ConvertFromString(item) – Bimo Mar 05 '18 at 12:07
  • No, it’s already there, (first code example) I just put some explanatory text between that and the foreach loop example (b/c I think it’s important for SO answers to explain what’s actually going on rather than just being a dump of code). It’s also better to do it outside the foreach loop, unlike in your answer where you create a new instance every time through the loop. – Dave M Mar 05 '18 at 12:21
  • This works for WPF... Any ideas how to do the same in UWP? new GridLengthConverter().ConvertFromString(item).. Seems they removed GridLengthConverter from UWP.. https://stackoverflow.com/questions/12495937/winrt-replacement-for-system-componentmodel-typeconverter – Bimo Mar 05 '18 at 12:32
  • Sorry, no experience with UWP – Dave M Mar 05 '18 at 12:41
-1

Complete answer from Dave M:

foreach (string item in items)
{
    GridLengthConverter converter = new GridLengthConverter();

    RowDefinitions.Add(
      new RowDefinition { 
        Height = (GridLength)converter.ConvertFromString(item) }
        );
}

The above answer works for WPF. If you are using UWP then you can use the code above by creating your own GridLengthConverter class, since this class doesn't come with UWP:

public class GridLengthConverter
{
    public GridLength ConvertFromString(string s)
    {
        if (s == "auto")
            return GridLength.Auto;
        else if (s == "*")
            return new GridLength(1, GridUnitType.Star);
        else
        {
            int pixels;
            int.TryParse(s, out pixels);
            var g = new GridLength(pixels);
            return g;
        }
    }
}
Bimo
  • 5,987
  • 2
  • 39
  • 61