Donnerstag, 17. März 2011

Get the property value by its path

/// <summary>

/// walks the property path and gets the value of the property on the object 'value'

/// example: path = "Company.Address[1].City"

/// </summary>

/// <param name="value">object to parse the property value from</param>

/// <param name="path">path to the property</param>

public static object FollowPropertyPath(object value, string path)

{

if (value == null) throw new ArgumentNullException("value");

if (path == null) throw new ArgumentNullException("path");

Type currentType = value.GetType();

object obj = value;

foreach (string propertyName in path.Split('.')) // split property path by "."

{

if (currentType != null)

{

PropertyInfo property = null;

int brackStart = propertyName.IndexOf("["); // parsing out if the property is an indexer property

int brackEnd = propertyName.IndexOf("]");

property = currentType.GetProperty(brackStart > 0 ? propertyName.Substring(0, brackStart) : propertyName);

obj = property.GetValue(obj, null);

if (brackStart > 0) // just for indexer properties

{

string index = propertyName.Substring(brackStart + 1, brackEnd - brackStart - 1); // get the index

// determine type of indexer property. extend the following if other types are required

foreach (Type iType in obj.GetType().GetInterfaces())

{

// http://stackoverflow.com/questions/852233/getting-values-of-a-generic-idictionary-using-reflection

if (iType.IsGenericType && iType.GetGenericTypeDefinition() == typeof(IDictionary<,>))

{

obj = typeof(ReflectorUtil).GetMethod("GetDictionaryElement")

.MakeGenericMethod(iType.GetGenericArguments())

.Invoke(null, new object[] { obj, index });

break;

}

if (iType.IsGenericType && iType.GetGenericTypeDefinition() == typeof(IList<>))

{

obj = typeof(ReflectorUtil).GetMethod("GetListElement")

.MakeGenericMethod(iType.GetGenericArguments())

.Invoke(null, new object[] { obj, index });

break;

}

}

}

// allow for derived properties in the path (property.PropertyType will get the defined type, obj.GetType the actual one)

currentType = obj != null ? obj.GetType() : null; //property.PropertyType;

}

else return null;

}

return obj;

}

public static TValue GetDictionaryElement<TKey, TValue>(IDictionary<TKey, TValue> dict, object index)

{

TKey key = (TKey)Convert.ChangeType(index, typeof(TKey), null);

return dict[key];

}

public static T GetListElement<T>(IList<T> list, object index)

{

return list[Convert.ToInt32(index)];

}

Dienstag, 23. November 2010

WPF Treeview Recursive Expand/Collapse

The following class contains an expansion method that allows for dynamic expansion and collapse of a WPF (untested with Silverlight, might work as well) TreeView. The second method parameter provides a way to define the depth of expansion/collapse.

public static class TreeViewExt

{

/// <summary>

/// Expands/collapses a treeview control recursively. Since for a hierarchical data template, the items will

/// only be generated when displayed - and only then can be expanded, the method attaches an event to the

/// StatusChanged event of the ItemsContainerGenerator and waits until they are in fact generated to recursively

/// call the expand method on these items.

/// </summary>

///

/// <param name="itemsControl"> ItemsControl, can be treeview or treeviewitem </param>

/// <param name="expand"> expand = false collapses, expand = true expands </param>

/// <param name="levelDepth"> for levelDepth = int.MaxValue, the entire tree will be expanded/collapsed.

/// For any other value n of levelDepth, only n levels away from the supplied itemsControl will be expanded

/// or collapsed to. </param>

public static void ExpandRecursively(this ItemsControl itemsControl, bool expand, int levelDepth)

{

// decrease level depth for next recursive call only if levelDepth != int.MaxValue

int depth = levelDepth == int.MaxValue ? levelDepth : levelDepth - 1;

// expand the item

TreeViewItem treeViewItem = itemsControl as TreeViewItem;

if (treeViewItem != null)

treeViewItem.IsExpanded = expand || levelDepth >= 0; // expand, or keep expanded when levelDepth >= 0

// continue if levelDepth is still bigger than 0, or if subitems need to be collapsed

if (levelDepth > 0 || !expand)

{

// get container generator of itemsControl

ItemContainerGenerator itemContainerGenerator = itemsControl.ItemContainerGenerator;

// if containers have already been generated, the subItems can be expanded/collapsed

if (itemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)

{

for (int i = itemsControl.Items.Count - 1; i >= 0; --i)

{

ItemsControl childControl = itemContainerGenerator.ContainerFromIndex(i) as ItemsControl;

if (childControl != null)

childControl.ExpandRecursively(expand, depth);

}

}

// otherwise, we have to wait for the containers to be generated. attach event to listen for status

else

{

EventHandler handler = null; // store in variable, so the handler can be detached

handler = new EventHandler((s, e) =>

{

if (itemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)

{

for (int i = itemsControl.Items.Count - 1; i >= 0; --i)

{

ItemsControl childControl = itemContainerGenerator.ContainerFromIndex(i) as ItemsControl;

if (childControl != null)

childControl.ExpandRecursively(expand, depth);

itemContainerGenerator.StatusChanged -= handler; // detach

}

}

});

itemContainerGenerator.StatusChanged += handler; // attach

}

}

}

}

Freitag, 15. Oktober 2010

Shrink database (SQL Studio 2008)

Database Properties > Options
  • Recovery model: Simple
  • Auto Shrink: True
Database Tasks > Shrink

Freitag, 9. Oktober 2009

SQL: transfer record from one database to another


/* The following snippet will copy the complete record with Id = 9 from

[databaseName1].[tableName] to [databaseName2].[tableName]*/


INSERT INTO databaseName1.dbo.tableName

SELECT * FROM databaseName2.dbo.tableName

WHERE tableName.Id = 9


Freitag, 19. Juni 2009

Fill Background of a Control with Gradient

        /// <summary>

        /// Paints a gradient to the Control's background

        /// </summary>

        /// <param name="ctrl">Control that needs the brush up</param>

        /// <param name="color1">e.g. Color.FromArgb(120, 180, 255), or Color.Yellow</param>

        /// <param name="color2"></param>

        /// <param name="angle">0: horizontal, 45: top-left to bottom-right, etc.</param>

        private void PaintGradientBackground(Control ctrl, Color color1, Color color2, float angle)

        {

            Rectangle rect = new Rectangle(ctrl.Location, ctrl.Size);

 

            System.Drawing.Drawing2D.LinearGradientBrush gradBrush =

                new System.Drawing.Drawing2D.LinearGradientBrush(rect, color1, color2, angle);

 

            Bitmap bmp = new Bitmap(rect.Width, rect.Height);

 

            Graphics g = Graphics.FromImage(bmp);

            g.FillRectangle(gradBrush, rect);

 

            ctrl.BackgroundImage = bmp;

            ctrl.BackgroundImageLayout = ImageLayout.Stretch;

        }

Adding Text with different color styles in RichTextBox


/// <summary>

/// Writing to a RichTextBox in different colors should be easy enough. The intiuitional way would be:

/// richTextBox1.Text += someText;

/// richTextBox1.Select(richTextBox1.Find(someText), someText.Length);

/// richTextBox1.SelectionColor = Color.Blue;

/// Which works but gets messed up when other text is added to the RichTextBox.

/// Adding SelectedText instead of just Text does the trick:

/// </summary>

foreach (string ws in WorksheetsRequired)

{

if (this.Worksheets.ContainsKey(ws))

{

string ok = "Worksheet " + ws + " found." + Environment.NewLine;

output.SelectionColor = Color.Green;

output.SelectedText += ok;

}

else

{

string error = "Worksheet " + ws + " could not be found." + Environment.NewLine;

output.SelectionColor = Color.Red;

output.SelectedText += error;

}


// scroll to bottom of rtb
output.SelectionStart = this.richTextBox1.Text.Length;

output.ScrollToCaret();

}

Dienstag, 12. Mai 2009

datatable to combobox


''' <summary>

''' Binds class names and captions to combobox

''' </summary>

''' <remarks>The order (DataSource after Diplay- and ValueMember) is important.

''' Changing this will put a DataRow into cbx.SelectedValue instead of a string.</remarks>

Private Sub FillSourceClassComboBox()

Dim dt As New DataTable()

dt.Columns.Add(DC_CLASSCAPTION, System.Type.GetType("System.String"))

dt.Columns.Add(DC_CLASSNAME, System.Type.GetType("System.String"))

Dim classes() As String = Me.GetAgent.GetClassNames()

For Each cls As String In classes

If Not IsNothing(cls) Then

Dim dr As DataRow = dt.NewRow()

dr(DC_CLASSCAPTION) = Me.GetAgent.EvidenceClass(cls).Caption

dr(DC_CLASSNAME) = cls

dt.Rows.Add(dr)

End If

Next

Dim dv As DataView = dt.DefaultView

dv.Sort = DC_CLASSCAPTION

cbxSourceClass.DisplayMember = DC_CLASSCAPTION

cbxSourceClass.ValueMember = DC_CLASSNAME

cbxSourceClass.DataSource = dv

' add handler only now, so method is not executed when binding datasource

AddHandler cbxSourceClass.SelectedIndexChanged, AddressOf cbxSourceClass_SelectedIndexChanged

cbxSourceClass.SelectedValue = Me.CurrentObject.AttributeValue(ATTR_SOURCECLASS)

End Sub