Saturday, October 8, 2016

WinForms RichTextBox Append Log and UIThread extensions

Turn any RichTextBox in winforms to a log view. Just call rtxt.AppendLog("someString"); and it will append that to a new line in the richtextbox. And scroll it to view.

public static void AppendLog(this RichTextBox rtxt, string s)
{
 rtxt.UIThread(() =>
 {
  rtxt.AppendText($"{s}{Environment.NewLine}");
  rtxt.SelectionLength = 0;
  if (rtxt.Lines.Length > 10000)
  {
   rtxt.Lines = rtxt.Lines.Skip(5000).ToArray();
  }
  rtxt.SelectionStart = rtxt.TextLength;
  rtxt.ScrollToCaret();
 });
}
The above snippet of code requires the following to function correctly.
static public void UIThread(this Control control, Action code)
{
 if (control.InvokeRequired)
 {
  control.BeginInvoke(code);
  return;
 }
 code.Invoke();
}
I can't take credit, found it years ago on some forum somewhere. But here it is anyway. It makes a call to a winforms control synschronize with the GUI thread so that no cross-threading exceptions is thrown. GUI items can only be modified from the GUI thread and this ensures just that.

The exception thrown if correct thread synchronization is not used is: 
System.InvalidOperationException was unhandled
  HResult=-2146233079
  Message=Cross-thread operation not valid: Control 'rtxtOutput' accessed from a thread other than the thread it was created on.
  Source=System.Windows.Forms
  StackTrace:
       at System.Windows.Forms.Control.get_Handle()
       at System.Windows.Forms.TextBoxBase.GetSelectionStartAndLength(Int32& start, Int32& length)
       at System.Windows.Forms.TextBoxBase.set_SelectionLength(Int32 value)
       at System.Windows.Forms.RichTextBox.set_SelectionLength(Int32 value)
       at ave.dev.winform.Form1.ticker_Tick(Object sender, EventArgs e) in C:\tfs\YYY\Form1.cs:line 54
       at ave.dev.winform.Form1._loggerHook_NewLogLine(String s) in C:\tfs\YYY\Form1.cs:line 38


Back to extensions list

Friday, October 7, 2016

Transform string to and from camel case.

Small piece of code to transform a string to and from camel case form. For anyone who find that kind of things useful.

private static readonly char[] Delimeters = {' '}; 
public static string ToCamelCase(string input)
{
 var sb = new StringBuilder();
 input = input.ToLowerInvariant();
 var split = input.Split(Delimeters, StringSplitOptions.RemoveEmptyEntries);
 foreach (var s in split)
 {
  for(int i = 0; i < s.Length; i++)
  {
   var c = s[i];
   sb.Append(i == 0 ? char.ToUpperInvariant(c) : c);
  }
 }
 return sb.ToString().Trim();
}

public static string FromCamelCaseToNormal(string input)
{
 var sb = new StringBuilder();
 foreach (var c in input)
 {
  if (char.IsUpper(c) 
   || char.IsDigit(c))
   sb.Append(" ");
  sb.Append(c);
 }
 return sb.ToString().Trim();
}

Saturday, October 1, 2016

Get random item from a list extension


private static Random _random = new Random();
public static T GetRandom<T>(this List<T> list)
{
    if (list.Count == 0)
        return default(T);
    if (list.Count == 1)
        return list[0];
    return list[_random.Next(0, list.Count)];
}

Very useful in a broad range of scenarios when you want to get a random element from a list.
Just call myList.GetRandom()

Back to extensions list