Convert numbers in a string array (#3, #1, #2, #4) to range (#1:#4)
In order to improve readability I'd say to not go too deep with the indentation. For example:

            if (IDs.Contains(plus1) &amp;&amp; IDs.Contains(plus2))
            {
                IDs.Remove(plus1);
                IDs.Remove(plus2);
                var toInt = fromInt + 2;
                while (IDs.Contains($"#{toInt + 1}"))
                {
                    toInt += 1;
                    IDs.Remove($"#{toInt}");
                }
                i = $"#{fromInt}:#{toInt}";
            }


can be transformed in:

if (!(IDs.Contains(plus1) &amp;&amp; IDs.Contains(plus2)))
{
    continue;
}
IDs.Remove(plus1);
IDs.Remove(plus2);
var toInt = fromInt + 2;
while (IDs.Contains($"#{toInt + 1}"))
{
    toInt += 1;
    IDs.Remove($"#{toInt}");
}
i = $"#{fromInt}:#{toInt}";


The same can be done with the conditions if (int.TryParse(i.Substring(1), out fromInt)) and if (i.StartsWith("#")) in the upper levels. 

The name of the string i is a little misleading. i is usually used as an index. I think id would be a proper name.

The resulting code could be transformed from:

var newIDs = new List&lt;string&gt;();
for (var index = 0; index &lt; IDs.Count; index++)
{
    var i = IDs[index];
    if (i.StartsWith("#"))
    {
        int fromInt;
        if (int.TryParse(i.Substring(1), out fromInt))
        {
            var plus1 = $"#{fromInt + 1}";
            var plus2 = $"#{fromInt + 2}";
            if (IDs.Contains(plus1) &amp;&amp; IDs.Contains(plus2))
            {
                IDs.Remove(plus1);
                IDs.Remove(plus2);
                var toInt = fromInt + 2;
                while (IDs.Contains($"#{toInt + 1}"))
                {
                    toInt += 1;
                    IDs.Remove($"#{toInt}");
                }
                i = $"#{fromInt}:#{toInt}";
            }
        }
    }
    newIDs.Add(i);
}
return string.Join(",", newIDs);


into the following:

var newIDs = new List&lt;string&gt;();
for (var index = 0; index &lt; IDs.Count; index++)
{
    var id = IDs[index];
    if (!id.StartsWith("#"))
    {
        newIDs.Add(i);
        continue;
    }
    int fromInt;
    if (!int.TryParse(i.Substring(1), out fromInt))
    {
        newIDs.Add(id);
        continue;
    }
    var plus1 = $"#{fromInt + 1}";
    var plus2 = $"#{fromInt + 2}";
    if (!(IDs.Contains(plus1) &amp;&amp; IDs.Contains(plus2)))
    {
        newIDs.Add(id);
        continue;
    }
    IDs.Remove(plus1);
    IDs.Remove(plus2);
    var toInt = fromInt + 2;
    while (IDs.Contains($"#{toInt + 1}"))
    {
        toInt += 1;
        IDs.Remove($"#{toInt}");
    }
    i = $"#{fromInt}:#{toInt}";
    newIDs.Add(id);
}
return string.Join(",", newIDs);