Featured Post

Organize and rename photos by EXIF data with PowerShell

This PowerShell script organizes and renames all photos in a selected folder using EXIF data. It will also create thumbnails of the images i...

Friday, December 27, 2013

Change TabControl SelectedTabItem in your ViewModel by TabItem Name or Header Value

Using these simple methods you can change your active tab in your ViewModel via commands or methods. If you want to change to a tab but don't want to have to track the tab index, you simply use the method that accepts the Tab Name or Header string name to change to that tab.

XAML:
<TabControl x:name="MyTabControl">...</TabControl>

Code Behind:
public MyUserControlorViewConstructor()
{
    InitializeComponent();
    
    MyViewModel mvm = new MyViewModel();
    DataContext = mvm;
    
    mvm.MyTabControl = MyTabControl;    
}

ViewModel:
public TabControl MyTabControl { get; set; }

public static void SetSelectedTab(string tabName)
{
    for (int i = 0; i < MyTabControl.Items.Count; i++)
    {
        TabItem item = MyTabControl.Items.GetItemAt(i) as TabItem;
        if (null == item || (item.Name != tabName && item.Header.ToString() != tabName)) continue;  
        MyTabControl.SelectedIndex = i;
        item.IsSelected = true;
        return;
    }
}

public static void SetSelectedTab(int tabIndex)
{
    TabItem item = MyTabControl.Items.GetItemAt(tabIndex) as TabItem;
    if (item == null) return;
    item.IsSelected = true;
    MyTabControl.SelectedIndex = tabIndex;
}

Sunday, December 8, 2013

All I want for Xmas is bitcoin!

Monday, November 11, 2013

(WPF) Creating a Custom Window

Here is what you will end up with, looks like a window doesn't it? But you can customize every aspect of it.



Create a new project of type Class Library named CustomControls.

CustomWindow.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace CustomControls
{
    public partial class CustomWindow : Window
    {
        #region Click events

        protected void MinimizeClick(object sender, RoutedEventArgs e)
        {
            WindowState = WindowState.Minimized;
        }

        protected void RestoreClick(object sender, RoutedEventArgs e)
        {
            WindowState = (WindowState == WindowState.Normal) ? WindowState.Maximized : WindowState.Normal;
        }

        protected virtual void CloseClick(object sender, RoutedEventArgs e)
        {
            Close();
        }

        #endregion

        static CustomWindow()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomWindow),
                new FrameworkPropertyMetadata(typeof(CustomWindow)));
        }

        public CustomWindow()
            : base()
        {
            PreviewMouseMove += OnPreviewMouseMove;
        }

        private HwndSource _hwndSource;

        protected override void OnInitialized(EventArgs e)
        {
            SourceInitialized += OnSourceInitialized;
            base.OnInitialized(e);
        }

        private void OnSourceInitialized(object sender, EventArgs e)
        {
            _hwndSource = (HwndSource)PresentationSource.FromVisual(this);
        }

        public override void OnApplyTemplate()
        {

            Rectangle moveRectangle = GetTemplateChild("moveRectangle") as Rectangle;
            if (moveRectangle != null)
                moveRectangle.PreviewMouseDown += moveRectangle_PreviewMouseDown;

            Button minimizeButton = GetTemplateChild("minimizeButton") as Button;
            if (minimizeButton != null)
                minimizeButton.Click += MinimizeClick;

            Button restoreButton = GetTemplateChild("restoreButton") as Button;
            if (restoreButton != null)
                restoreButton.Click += RestoreClick;

            Button closeButton = GetTemplateChild("closeButton") as Button;
            if (closeButton != null)
                closeButton.Click += CloseClick;

            Grid resizeGrid = GetTemplateChild("resizeGrid") as Grid;
            if (resizeGrid != null)
            {
                foreach (UIElement element in resizeGrid.Children)
                {
                    Rectangle resizeRectangle = element as Rectangle;
                    if (resizeRectangle != null)
                    {
                        resizeRectangle.PreviewMouseDown += ResizeRectangle_PreviewMouseDown;
                        resizeRectangle.MouseMove += ResizeRectangle_MouseMove;
                    }
                }
            }

            base.OnApplyTemplate();
        }

        protected void ResizeRectangle_MouseMove(Object sender, MouseEventArgs e)
        {
            Rectangle rectangle = sender as Rectangle;
            switch (rectangle.Name)
            {
                case "top":
                    Cursor = Cursors.SizeNS;
                    break;
                case "bottom":
                    Cursor = Cursors.SizeNS;
                    break;
                case "left":
                    Cursor = Cursors.SizeWE;
                    break;
                case "right":
                    Cursor = Cursors.SizeWE;
                    break;
                case "topLeft":
                    Cursor = Cursors.SizeNWSE;
                    break;
                case "topRight":
                    Cursor = Cursors.SizeNESW;
                    break;
                case "bottomLeft":
                    Cursor = Cursors.SizeNESW;
                    break;
                case "bottomRight":
                    Cursor = Cursors.SizeNWSE;
                    break;
                default:
                    break;
            }
        }

        private void moveRectangle_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (Mouse.LeftButton == MouseButtonState.Pressed)
                DragMove();
        }

        protected void OnPreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (Mouse.LeftButton != MouseButtonState.Pressed)
                Cursor = Cursors.Arrow;
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam);

        protected void ResizeRectangle_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            Rectangle rectangle = sender as Rectangle;
            switch (rectangle.Name)
            {
                case "top":
                    Cursor = Cursors.SizeNS;
                    ResizeWindow(ResizeDirection.Top);
                    break;
                case "bottom":
                    Cursor = Cursors.SizeNS;
                    ResizeWindow(ResizeDirection.Bottom);
                    break;
                case "left":
                    Cursor = Cursors.SizeWE;
                    ResizeWindow(ResizeDirection.Left);
                    break;
                case "right":
                    Cursor = Cursors.SizeWE;
                    ResizeWindow(ResizeDirection.Right);
                    break;
                case "topLeft":
                    Cursor = Cursors.SizeNWSE;
                    ResizeWindow(ResizeDirection.TopLeft);
                    break;
                case "topRight":
                    Cursor = Cursors.SizeNESW;
                    ResizeWindow(ResizeDirection.TopRight);
                    break;
                case "bottomLeft":
                    Cursor = Cursors.SizeNESW;
                    ResizeWindow(ResizeDirection.BottomLeft);
                    break;
                case "bottomRight":
                    Cursor = Cursors.SizeNWSE;
                    ResizeWindow(ResizeDirection.BottomRight);
                    break;
                default:
                    break;
            }
        }

        private void ResizeWindow(ResizeDirection direction)
        {
            SendMessage(_hwndSource.Handle, 0x112, (IntPtr)(61440 + direction), IntPtr.Zero);
        }

        private enum ResizeDirection
        {
            Left = 1,
            Right = 2,
            Top = 3,
            TopLeft = 4,
            TopRight = 5,
            Bottom = 6,
            BottomLeft = 7,
            BottomRight = 8,
        }
    }
}

Themes\Generic.xaml

<resourcedictionary xmlns:local="clr-namespace:CustomControls" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">

    <!-- Window Button style -->
    <style targettype="{x:Type Button}" x:key="WindowButtonStyle">
        <setter Property="Background" Value="Transparent"/>
        <setter Property="Foreground" Value="{DynamicResource GreyLightBrush}" />
        <setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
        <setter Property="FontFamily" Value="Webdings"/>
        <setter Property="FontSize" Value="13.333" />
        <setter Property="Margin" Value="1,1,1,0"/>
        <setter Property="Template">
            <Setter.Value>
                <controltemplate TargetType="{x:Type ButtonBase}">
                    <border x:Name="Chrome"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            Background="{TemplateBinding Background}"
                            Margin="0"
                            SnapsToDevicePixels="True">
                        <ContentPresenter
                                ContentTemplate="{TemplateBinding ContentTemplate}"
                                Content="{TemplateBinding Content}"
                                ContentStringFormat="{TemplateBinding ContentStringFormat}"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                Margin="{TemplateBinding Padding}"
                                RecognizesAccessKey="True"
                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <trigger Property="IsMouseOver" Value="True">
                <setter Property="Foreground" Value="{DynamicResource WhiteBrush}" />
            </Trigger>
        </Style.Triggers>
    </style>

    <!-- Window style -->
    <style targettype="{x:Type local:CustomWindow}">
        <setter Property="WindowStyle" Value="None"/>
        <setter Property="ResizeMode" Value="NoResize"/>
        <setter Property="Foreground" Value="{DynamicResource ForegroundBrush}" />
        <setter Property="Background" Value="{DynamicResource BackgroundBrush}"/>
        <setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
        <setter Property="BorderThickness" Value="1"/>        
        <setter Property="Template">
            <Setter.Value>
                <controltemplate TargetType="{x:Type local:CustomWindow}">
                    <border BorderThickness="{TemplateBinding BorderThickness}"
                            BorderBrush="{TemplateBinding BorderBrush}">
                        <grid>
                            <grid>
                                <Grid.RowDefinitions>
                                    <rowdefinition Height="Auto"/>
                                    <rowdefinition />
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <columndefinition />
                                    <columndefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <rectangle x:Name="moveRectangle" Fill="Transparent" Grid.Row="0" Grid.Column="0"/>
                                <textblock x:Name="windowTitle" Margin="10 0"
                                           FontSize="16"
                                           Grid.Column="0" Grid.Row="0" Panel.ZIndex="-1"
                                           Foreground="{DynamicResource GreyLightBrush}"
                                           Text="{TemplateBinding Title}"/>
                                <stackpanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
                                    <button x:Name="minimizeButton" Style="{StaticResource WindowButtonStyle}"
                                            Content="0" />
                                    <button x:Name="restoreButton" Style="{StaticResource WindowButtonStyle}"
                                            Content="1" />
                                    <button x:Name="closeButton" Style="{StaticResource WindowButtonStyle}"
                                            Content="r" />
                                </StackPanel>
                                <grid Background="{TemplateBinding Background}"
                                           Grid.Row="1" Grid.ColumnSpan="2" Margin="5,5,5,5">
                                    <adornerdecorator>
                                        <ContentPresenter/>
                                    </AdornerDecorator>
                                </Grid>
                            </Grid>

                            <grid x:Name="resizeGrid">
                                <Rectangle
                                    Stroke="{x:Null}"
                                    Fill="Transparent"
                                    VerticalAlignment="Top"
                                    Height="5"
                                    x:Name="top"
                                    Margin="5,0,5,0" />
                                <Rectangle
                                    Stroke="{x:Null}"
                                    Fill="Transparent"
                                    x:Name="bottom"
                                    Height="5"
                                    VerticalAlignment="Bottom"
                                    Margin="5,0,5,0" />
                                <Rectangle
                                    Stroke="{x:Null}"
                                    Fill="Transparent"
                                    HorizontalAlignment="Left"
                                    Margin="0,5,0,5"
                                    Width="5"
                                    x:Name="left"/>
                                <Rectangle
                                    Stroke="{x:Null}"
                                    Fill="Transparent"
                                    Margin="0,5,0,5"
                                    Width="5"
                                    HorizontalAlignment="Right"
                                    x:Name="right" />
                                <Rectangle
                                    Stroke="{x:Null}"
                                    Fill="Transparent"
                                    HorizontalAlignment="Left"
                                    VerticalAlignment="Bottom"
                                    Width="5"
                                    Height="5"
                                    x:Name="bottomLeft" />
                                <Rectangle
                                    Stroke="{x:Null}"
                                    Fill="Transparent"
                                    VerticalAlignment="Bottom"
                                    Height="5"
                                    Width="5"
                                    HorizontalAlignment="Right"
                                    x:Name="bottomRight" />
                                <Rectangle
                                    Stroke="{x:Null}"
                                    Fill="Transparent"
                                    HorizontalAlignment="Right"
                                    Width="5"
                                    Height="5"
                                    VerticalAlignment="Top"
                                    x:Name="topRight" />
                                <Rectangle
                                    Stroke="{x:Null}"
                                    Fill="Transparent"
                                    HorizontalAlignment="Left"
                                    Width="6"
                                    VerticalAlignment="Top"
                                    Height="5"
                                    x:Name="topLeft" />
                            </Grid>

                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </style>
</resourcedictionary>

Now you can include this custom controls project as a reference in whichever project you want to use the custom window. After adding it as a reference, here is how to implement it, very simple!

MainWindow.xaml

<control:customwindow height="350" title="MainWindow" width="525"
        x:class="YourApp.MainWindow"
        xmlns:control="clr-namespace:CustomControls;assembly=CustomControls"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <grid>
        
    </grid>
</control:customwindow>


And in the code behind we inherit from our custom class:

MainWindow.xaml.cs
public partial class MainWindow : CustomControls.CustomWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }
}


Monday, November 4, 2013

(C#) Friendly names for enums

Enums are quick and easy. Here is how to have a friendly name for your enum value to display on the UI.

public enum CustomEnum
{
    [System.ComponentModel.Description("I am Alpha")]
    Alpha,
    [System.ComponentModel.Description("Beta Friendly Label")]
    Beta
}

public static class EnumHelper
{
    public static string GetEnumDescription(Enum value)
    {
        System.Reflection.FieldInfo fi = value.GetType().GetField(value.ToString());

        System.ComponentModel.DescriptionAttribute[] attributes =
            (System.ComponentModel.DescriptionAttribute[])fi.GetCustomAttributes(
            typeof(System.ComponentModel.DescriptionAttribute),
            false);

        if (attributes != null &&
            attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return value.ToString();
        }
    }
}

Usage:
MessageBox.Show(EnumHelper.GetEnumDescription(CustomEnum.Alpha));

Tuesday, October 29, 2013

BackgroundWorker Example for C#/WPF

Here is a simple example of how to use a BackgroundWorker to execute long running tasks without freezing the UI. This allows you to use ProgressChanged event handler to change your UI with status messages making for a much friendlier user experience.

In this example I am creating and populating a database which takes a minute or so to complete. With my Simple Elegant Busy Indicator for WPF bound to the BusyIndicator property, it lets the user know the application is busy and not frozen.


private void Execute()
{
    // Set status
    BusyIndicator = true;
    Status = "Creating database, please wait. This may take several minutes...";

    // Create Database background worker
    CreateDatabaseWorker = new BackgroundWorker();
    CreateDatabaseWorker.WorkerReportsProgress = true;
    CreateDatabaseWorker.DoWork += new DoWorkEventHandler(CreateDatabase_DoWork);
    CreateDatabaseWorker.ProgressChanged += new ProgressChangedEventHandler(CreateDatabase_WorkerProgressChanged);
    CreateDatabaseWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CreateDatabase_WorkCompleted);
    CreateDatabaseWorker.RunWorkerAsync();
}

// Note: You cannot modify any UI bound property in the _DoWork method
private void CreateDatabase_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        // Long running methods go here
        CreateDatabaseWorker.ReportProgress(25, "Creating employees...");
        Utilities.PopulateDBModel.CreateInitialEmployees();

        CreateDatabaseWorker.ReportProgress(50, "Creating countries and regions...");
        Utilities.PopulateDBModel.CreateCountries();
    }
    catch (Exception ex)
    {
        // If anything fails we set our result to false
        CreateDatabaseWorker.ReportProgress(100, "Error...");
        e.Result = false;
        return;
    }
    e.Result = true;
}

// This will update our UI while our background worker is... working
private void CreateDatabase_WorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
    if (e.UserState != null)
    {
        ProgressBarValue = e.ProgressPercentage;
        Status = e.UserState.ToString();
    }
}

// Now we can evaluate our results
private void CreateDatabase_WorkCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    BusyIndicator = false;

    if ((bool)e.Result != true)
    {
        ShowFailure = true;
        return;
    }

    ShowSuccess = true;
    Status = "Database created successfully!";
}

Wednesday, October 23, 2013

Visual Studio Pre-Build Event Script to Automatically Incremement Version Number

Using this post you will be able to change Visual Studio to 'Release Mode' and by building the project it runs a batch script which will prompt you for what version you want to set in the assembly files before building the project. The choices are No Change, Auto Increment, or Manually entering the build you want to use. This allows you to skip the prompt if you use 'Debug' mode, which will build using the existing version.

Right click project, select Properties > Build Events

In the "Pre-build event command line" box, put the following:

if "$(ConfigurationName)" == "Release" start "Version" /D "$(SolutionDir)" /WAIT Version.bat

There are 3 files to make this work, these files need a Solution Folder to reside in:

Right click solution, select Add > New Solution Folder

Now, create these 3 files:

Version.bat - Executed by Visual Studio pre-build event

@powershell -ExecutionPolicy Unrestricted -File "%~dp0Version.ps1"

For more information on the variable %~dp0 click here

Version.txt - Your starting version number

1.0.0.0

Version.ps1 - PowerShell script that is executed by Version.bat which actually increments Version number where needed

param (
    [string]$mode = "debug"
)

Write-Host "##########################"
Write-Host "# Version.ps1"
Write-Host "##########################"
Write-Host "#"
Write-Host "# This script will increment (if chosen) and set the version number in the"
Write-Host "# appropriate assembly files throughout the project before compiling continues"
Write-Host "#"
Write-Host "##########################"
Write-Host ""

trap
{
    Write-Error $_
    exit 1
}

################
# Example Script Usage
################
# @powershell -ExecutionPolicy Unrestricted -File "%~dp0Version.ps1"

####################
# Example Method Usage
####################

# Set-VersionFile -File $versionFilePath -Version $newVersion
# Set-VersionInAssemblyInfo -File ($scriptDirectory + "\ProfitPOS\Properties\AssemblyInfo.cs") -Version $newVersion
# Set-VersionInAssemblyInfo -File ($scriptDirectory + "\..\BootstrapperCustom\Properties\AssemblyInfo.cs") -Version $newVersion
# Set-VersionInWixGlobal -File ($scriptDirectory + "\..\Setup\Variables.wxi") -Version $newVersion
# Set-VersionInAssemblyReference -File ($scriptDirectory + "\MyProduct.Assembly3\App.config") -AssemblyName "MyProduct.Assembly2" -Version $newVersion
# Set-VersionInBindingRedirect -File ($scriptDirectory + "\MyProduct.Assembly4\Web.config") -AssemblyName "Other.Component" -Version $otherVersion

##########
# Methods
##########

function Update-Version ([Version]$Version)
{
    $date = (Get-Date).ToUniversalTime()
    #$newBuild = $date.ToString("yyMM")
    #$dayRevisionMin = $date.Day * 1000
    #if (($Version.Build -lt $newBuild) -or ($Version.Revision -lt $dayRevisionMin)) { $newRevision = $dayRevisionMin + 1 } else { $newRevision = $Version.Revision + 1 }

 # This forces new build each time for major upgrades to work, revision is ignored by windows installer
 $newBuild = $Version.Build + 1
 #$newRevision = $date.ToString("HHMMss") / 4
 $newRevision = $Version.Revision

    New-Object -TypeName System.Version -ArgumentList $Version.Major, $Version.Minor, $newBuild, $newRevision
}
 
function Get-VersionFile ([String]$File)
{
    #Write-Host ("Reading version file " + $File)
    #Write-Host ""
    $versionString = [System.IO.File]::ReadAllText($File).Trim()
    New-Object -TypeName System.Version -ArgumentList $versionString
}
 
function Set-VersionFile ([String]$File, [Version]$Version)
{
    #Write-Host ("Writing version file " + $File)
    #Write-Host ""
    [System.IO.File]::WriteAllText($File, $Version.ToString())
}
 
function Set-VersionInAssemblyInfo ([String]$File, [Version]$Version)
{
    Write-Host ("Setting version in assembly info file " + $File)
    Write-Host ""
    $contents = [System.IO.File]::ReadAllText($File)
    $contents = [RegEx]::Replace($contents, "(AssemblyVersion\("")(?:\d+\.\d+\.\d+\.\d+)(""\))", ("`${1}" + $Version.ToString() + "`${2}"))
    $contents = [RegEx]::Replace($contents, "(AssemblyFileVersion\("")(?:\d+\.\d+\.\d+\.\d+)(""\))", ("`${1}" + $Version.ToString() + "`${2}"))
    [System.IO.File]::WriteAllText($File, $contents)
}
 
function Set-VersionInWixGlobal ([String]$File, [Version]$Version)
{
    Write-Host ("Setting version in WIX global file " + $File)
    Write-Host ""
    $contents = [System.IO.File]::ReadAllText($File)
    $contents = [RegEx]::Replace($contents, "(\<\?define\s*ProductVersion\s*=\s*"")(?:\d+\.\d+\.\d+\.\d+)(""\s*\?\>)", ("`${1}" + $Version.ToString() + "`${2}"))
    [System.IO.File]::WriteAllText($File, $contents)
}
 
function Set-VersionInAssemblyReference ([String]$File, [String]$AssemblyName, [Version]$Version)
{
    Write-Host ("Setting version in assembly references of " + $File)
    Write-Host ""
    $contents = [System.IO.File]::ReadAllText($File)
    $contents = [RegEx]::Replace($contents, "(["">](?:\S+,\s+){0,1}" + $AssemblyName + ",\s+Version=)(?:\d+\.\d+\.\d+\.\d+)([,""<])", ("`${1}" + $Version.ToString() + "`${2}"))
    [System.IO.File]::WriteAllText($File, $contents)
}
 
function Set-VersionInBindingRedirect ([String]$File, [String]$AssemblyName, [Version]$Version)
{
    Write-Host ("Setting version in binding redirects of " + $File)
    Write-Host ""
    $contents = [System.IO.File]::ReadAllText($File)
    $oldVersionMax = New-Object -TypeName "System.Version" -ArgumentList $Version.Major, $Version.Minor, $Version.Build, ($Version.Revision - 1)
    $pattern = "([\s\S]*?<assemblyIdentity\s+name=""" + $AssemblyName + """[\s\S]+?/>[\s\S]*?<bindingRedirect\s+oldVersion=""\d+\.\d+\.\d+\.\d+-)(?:\d+\.\d+\.\d+\.\d+)(""\s+newVersion="")(?:\d+\.\d+\.\d+\.\d+)(""[\s\S]*?/>)"
    $contents = [RegEx]::Replace($contents, $pattern, ("`${1}" + $oldVersionMax.ToString() + "`${2}" + $Version.ToString() + "`${3}"))
    [System.IO.File]::WriteAllText($File, $contents)
}

########
# Begin
########
$scriptDirectory =  [System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Definition)
$versionFilePath = $scriptDirectory + "\Version.txt"

$oldVersion = Get-VersionFile -File $versionFilePath
$newVersion = Update-Version -Version $oldVersion

Write-Host ("[Enter] for Current Version: " + $oldVersion.ToString());
Write-Host ""
Write-Host ("[B] for New Build Version: " + $newVersion.ToString());
Write-Host ""
Write-Host "Or enter a Custom Version, example: 1.2.3.4";
Write-Host ""
Write-Host ""

$mode = Read-Host "Which version do you want to use?"
Write-Host ""

if ($mode.ToLower().Contains("b"))
{
    Write-Host ""
    Write-Host ("Using New Build Version: " + $newVersion.ToString())
}
elseif ($mode.length -lt 1)
{
    $newVersion = $oldVersion
    Write-Host ""
    Write-Host ("Using Current Version: " + $newVersion.ToString())
}
else
{
    $modes = $mode.Split(".")
    $newVersion = New-Object -TypeName System.Version -ArgumentList $modes[0], $modes[1], $modes[2], $modes[3]
    Write-Host ""
    Write-Host ("Using Custom Version: " + $newVersion.ToString())
}
    
Write-Host ""
Write-Host ""

Set-VersionFile -File $versionFilePath -Version $newVersion
Set-VersionInAssemblyInfo -File ($scriptDirectory + "\ProfitPOS\Properties\AssemblyInfo.cs") -Version $newVersion
Set-VersionInAssemblyInfo -File ($scriptDirectory + "\..\BootstrapperCustom\Properties\AssemblyInfo.cs") -Version $newVersion
Set-VersionInWixGlobal -File ($scriptDirectory + "\..\Setup\Variables.wxi") -Version $newVersion

Write-Host ""
Write-Host "Done!"
Write-Host ""

Read-Host "Hit enter to exit"
exit 0

Friday, October 18, 2013

Simple Elegant Busy Indicator for WPF

<Control Grid.Column="0" Grid.Row="3"
            Grid.ColumnSpan="1" Grid.RowSpan="1"
            Width="100" Height="100" VerticalAlignment="Top"  HorizontalAlignment="Left">
    <Control.Style>
        <Style TargetType="Control">
            <Setter Property="Foreground" Value="White" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Control">
                        <Viewbox>
                            <Canvas RenderTransformOrigin="0.5,0.5" Width="100" Height="100">
                                <Canvas.Resources>
                                    <Style TargetType="{x:Type Ellipse}">
                                        <Setter Property="Stretch" Value="Fill"/>
                                        <Setter Property="Fill" Value="Black"/>
                                    </Style>
                                </Canvas.Resources>
                                <Ellipse Width="21.835" Height="21.862" Canvas.Left="20.1696" Canvas.Top="9.76358" Opacity="1.0"/>
                                <Ellipse Width="20.835" Height="20.862" Canvas.Left="2.86816" Canvas.Top="29.9581" Opacity="0.9"/>
                                <Ellipse Width="19.835" Height="19.862" Canvas.Left="0.00001" Canvas.Top="57.9341" Opacity="0.8"/>
                                <Ellipse Width="17.835" Height="17.862" Canvas.Left="12.1203" Canvas.Top="83.3163" Opacity="0.7"/>
                                <Ellipse Width="16.835" Height="16.862" Canvas.Left="36.5459" Canvas.Top="98.1380" Opacity="0.6"/>
                                <Ellipse Width="14.835" Height="14.862" Canvas.Left="64.6723" Canvas.Top="96.8411" Opacity="0.5"/>
                                <Ellipse Width="13.835" Height="13.862" Canvas.Left="87.6176" Canvas.Top="81.2783" Opacity="0.4"/>
                                <Ellipse Width="12.835" Height="12.862" Canvas.Left="98.165"  Canvas.Top="54.4140" Opacity="0.3"/>
                                <Ellipse Width="11.835" Height="11.862" Canvas.Left="92.9838" Canvas.Top="26.9938" Opacity="0.2"/>
                                <Canvas.RenderTransform>
                                    <RotateTransform x:Name="SpinnerRotate" Angle="0"/>
                                </Canvas.RenderTransform>
                                <Canvas.Triggers>
                                    <EventTrigger RoutedEvent="ContentControl.Loaded">
                                        <BeginStoryboard>
                                            <Storyboard>
                                                <DoubleAnimation Storyboard.TargetName="SpinnerRotate" Storyboard.TargetProperty="Angle" From="0" To="360" Duration="0:0:01.3" RepeatBehavior="Forever"/>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                </Canvas.Triggers>
                            </Canvas>
                        </Viewbox>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Control.Style>
</Control>

You can easily bind the Visibility to a property to control when it is shown/hidden:
Visibility="{Binding ShowThinking, Converter={StaticResource BooleanToVisibilityConverter}}"
Derived from: http://stackoverflow.com/a/8668682/1992193

Going Home Friday vs Going Work Monday (Video)

Wednesday, October 16, 2013

Password Strength

from http://xkcd.com/936/

Configuring Headless VirtualBox Server on CentOS 6.x

If you are starting on a blank server, I would recommend first using my Server Provisioning Script to get the server secured and updated.

The most important thing is to make sure that you have the Source available for your current Kernel.

Get current kernel information:

[user@server] uname -r

2.6.32-358.6.2.el6.x86_64

Get which kernels are installed:

[user@server] rpm -qa | grep kernel

kernel-devel-2.6.32-358.18.1.el6.x86_64 kernel-firmware-2.6.32-358.18.1.el6.noarch kernel-headers-2.6.32-358.18.1.el6.x86_64 dracut-kernel-004-303.el6.noarch kernel-2.6.32-358.0.1.el6.x86_64 kernel-2.6.32-358.18.1.el6.x86_64 kernel-2.6.32-358.14.1.el6.x86_64


In the example above I am using kernel 2.6.32-358.6.2.el6.x86_64 while the rpms that are installed are for a newer version 2.6.32-358.18.1.el6.x86_64

So, in this example, we must remove the newer rpms (18.1) and install the ones that match our current kernel (6.2). Note: You should only have to do this for the headers and not devel.

sudo yum remove kernel-headers-2.6.32-358.18.1.el6.x86_64

Now we can install the ones to match:

sudo yum install kernel-headers-2.6.32-358.6.2.el6.x86_64
sudo yum install kernel-devel-2.6.32-358.6.2.el6.x86_64

Now we can get on with the rest:

cd /etc/yum.repos.d
sudo wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm
sudo rpm -Uvh rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm

sudo wget http://mirror.pnl.gov/epel/6/i386/epel-release-6-8.noarch.rpm
sudo rpm -Uvh epel-release-6-8.noarch.rpm
sudo yum -y --enablerepo rpmforge install dkms

sudo yum -y groupinstall "Development Tools"

sudo reboot

Once the server reboots:

cd /etc/yum.repos.d
sudo wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo
sudo yum -y install VirtualBox-4.2


cd /tmp
sudo wget http://download.virtualbox.org/virtualbox/4.2.8/Oracle_VM_VirtualBox_Extension_Pack-4.2.8-83876.vbox-extpack
sudo VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-4.2.8-83876.vbox-extpack


That should be it! Now you have VirtualBox 4.2 installed and ready to rock!

Monday, October 14, 2013

CentOS 6.x LAMP Server Provisioning Script


1) Log onto server as root
2) Download the latest version of the script using wget:
wget https://gist.github.com/dirte/5328929/raw/bd45dba4195147e026ffdd1d7557172bdcb72edb/provision_centos_server.sh

3) Set the script to be executable:

chmod +x ./provision_centos_server.sh

4) Execute the script:

./provision_centos_server.sh

Follow the scripts prompts and when it completes, reboot the server.

reboot

Once the server is rebooted, it will now no longer permit the root user to login through SSH. You will need to login using your admin user you created. Also, if you changed the SSH port, be sure to connect to the new port!

Note: There are further notes in the script on how to do initial configuration for Apache, MySQL and PHP. There is an 'exit' in the script before these notes, so if you want to use any of the commands there you will need to do so manually.

Tuesday, October 8, 2013

C# WPF/Silverlight MVVM Beginners Tutorial 101 Part I

Welcome to a multi-part tutorial to help walk you through how to get started developing a WPF or Silverlight application utilizing the MVVM design pattern.

MVVM = Model, View, ViewModel

Our ViewModels primary role is to control the data displayed on our View, data pulled from our Model. The Microsoft Prism library supplies (among other things we can use later) the NotificationObject class which we will use to Notify our View when Properties Change.

Each of our ViewModels will inherit from our BaseViewModel class that we will create first.

Prerequisites

Using VisualStudio, start a New Project > Visual C# > Silverlight > Silverlight Application

Note: We use Silverlight for Web applications and WPF for Desktop applications. Most Silverlight controls are supported in WPF while there are some WPF controls that are not available in Silverlight, so it would be recommended to design your application using Silverlight to be compatible on both platforms. See Contrasting Silverlight and WPF for more information.

Using NuGet, install Prism to supply our NotifyPropertyChanged utilities:

Visual Studio > Tools > Library Package Manager > Package Manager Console

PM> Install-Package Prism

Now the Prism dll files have been added to your Project References folder and we can refer to the Prism Namespace in our code.

On to the code

Create a new Class: BaseViewModel.cs

At the top, include the Prism references, and the class inherits from Prism's NotificationObject:

BaseViewModel.cs:

using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.ViewModel;

namespace MyApp
{
    public class BaseViewModel : NotificationObject
    {
    }
}

Lets create a new Class: CarrotViewModel.cs

namespace MyApp
{
    public class CarrotViewModel : BaseViewModel
    {
    }
}

Because our CarrotViewModel inherits from our BaseViewModel, which inherits from Prism NotificationObject, any Property in our CarrotViewModel can now support RaisePropertyChanged method.

In Part II we will add some Properties and have them update our UI, after all that is the whole point of an application usually!

to be continued in Part II...