.Net ramblings
# Friday, 14 October 2011
Asus P6T deluxe v2 overclock settings with Intel i7 920
Found a safe/low-temp overclock @ 3.6Ghz for this board. Using 1600Mhz DDR3 RAM. standard air cooling in a z-machine GT1000 case.

RAM set to XMP profile #1. 8/8/8/24/1.66V/1.35v
BCLK:180
PCIE:100
Speedstep/turbotech:enable
RAM:~1450 Mhz
CPU Volt:1.25V
QPI/DRAM:1.35V
DRAM bus:1.66v

everything else auto/default
CPU Fan and chassis fan set to Standard profile.

44c @ idle. 66c under orthos CPU stress test.  The 1.25 CPU voltage keeps the temps nice and low, and it's very stable.  the 920 does this o'c with ease, could probably go lower but stability is more of a priority for a software dev PC.


Friday, 14 October 2011 13:42:08 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  General

# Monday, 24 January 2011
Playing a DVD remotely from a network share
you can rip a DVD and then stream the file to a remote computer, or with VLC media player you can stream the DVD itself, but that takes a bit of setting up.  i wanted to pop a DVD into my desktop PC and then play it remotely from a netbook plugged in to the TV.  so i share out the DVD drive on the desktop, all well and good, i can see the VIDEO_TS and AUDIO_TS folders on the netbook, but there isn't an Autoplay option or any way to 'start' the DVD.  i found a useful tip from the VLC forums, you can drag the VIDEO_TS folder into VLC (on the netbook, for example) and then it will start playing the DVD, with full support for menus and chapters etc.  The bit i got stuck on was that you have to start the DVD for a few seconds on the host PC (desktop in my case) which authenticates the disc and allows it to be streamed. 

not very high tech, but handy, if you ever find yourself without a DVD player.


Monday, 24 January 2011 20:43:52 (GMT Standard Time, UTC+00:00)  #    Comments [0]  General

# Tuesday, 14 September 2010
Gridview Delete via LinqDataSource fails with ChangeConflictException: Row not found or changed
if you use SqlMetal to generate DataContext classes against an SQL database, you might run into some problems with GridView and deleting a row, when using a LinqDataSource.
this was a very frustrating problem to track down, apparently there is a bug in the LinqDataSource with datetime fields.  i kept getting this error: ChangeConflictException: Row not found or changed
and there was no apparent reason why it was happening, because the same code worked for other tables.  I eventually narrowed it down to the only difference between the two tables, a non nullable datetime field. changing this field to nullable removed the problem.
this thread was useful in troubleshooting the problem.
i also found that calling DataBind() on the LinqDataSource before re-binding the GridView helped get rid of this error message.


Tuesday, 14 September 2010 12:50:05 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  .Net General | Database

# Thursday, 17 June 2010
Nokia Ovi Suite Calendar Sync Cancelled error message
I have a nokia E52 and in general i'm very happy with the Nokia Ovi Suite software.  But today it refused to synchronise my calendar with a "Sync Cancelled" error message, other items synchronised fine.  The solution was to reset the nokia profile/files on my computer.  Make sure to close Outlook, Ovi Suite, and end the "nokiamserver.exe" process.  Then open up explorer and browse to C:\Users\Name\AppData\Local and C:\Users\Tim\AppData\Roaming.  You could delete these files, but just in case i renamed the "Nokia" and "Nokia Ovi Suite" folders to "xNokia" and "xNokia Ovi Suite".  If anything goes wrong you can always rename them back to their original names.
Then open up Ovi Suite again and reconnect the phone.  It should synchronise fine then, there must be some bug with the calendar synchronisation that can corrupt the local database.


Thursday, 17 June 2010 09:44:58 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  General

# Friday, 11 June 2010
Excel interop with Asp.Net
Ran into a permissions problem today using Excel interop code from within ASP.Net, which had worked fine from a windows forms application.
Thanks to 'Frosty' for his post which explains how to enable the appropriate permissions, reproducing it here in case the link ever goes down:

From command prompt / start->run... type dcomcnfg

Select Component Services->Computers->My Compter->DCOM Config

Scroll down and select Microsoft Excel Applicaton

Right click on Microsoft Excel Applicaton and select properties.

Select the Security tab

In Launch Permissions group box click Edit button.

Add the appropriate user for your particular situation. In my case, I
selected MyDomainName\Domain Users.

Make sure that Allow check box is checked for your appropriate user.

Click OK

In Access Permissions group box click Edit button.

Add the appropriate user for your particular situation. In my case, I
selected MyDomainName\Domain Users.

Make sure that Allow check box is checked for your appropriate user.

Click OK

Excel interop will now work via asp.net


Friday, 11 June 2010 18:32:37 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  Asp.Net

# Wednesday, 26 May 2010
Compact Framework - Using the Treeview to replace the ListBox
As any compact framework developer will tell you, the out-of-the-box ListBox control is a bit crap because it doesn't support horizontal scrolling.  what were they thinking??
anyway, after several work-arounds to this problem, i finally realised that the treeview control does support horizontal scrolling, and you can load up a treeview to look just like a listbox, having all the nodes added at the top level, i.e. a "flat" treeview.
the extra bonus with this approach is that Windows Mobile 6.5 has a brilliant touch friendly Treeview control that you can finger-drag up and down and left and right (at least the HTC HD2 has this, i can't vouch for other devices).

i've included a "Chooser" class i wrote to make user selections easy to code for.  to use the class, use the following approach, the SelectedItem string is kept as a static variable in the Form so you can close and dispose the form straight away, and still catch the "return" value of the form. If you pass in the parameter to use Checkboxes, you can access the CheckedItems static property which is a List<string>.
Chooser c = new Chooser("Select Item", new string[]{"Option 1", "Option 2", "Option 3"}, true, true); 
DialogResult d = c.ShowDialog();
c.Dispose();
if(d != DialogResult.Cancel)
MessageBox.Show("You chose " + Chooser.SelectedItem);
here's the class then:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace IbenzaMobileUtil
{
public partial class Chooser : Form
{
private MainMenu mainMenu1;
private MenuItem mmOK;
private MenuItem mmCancel;
private Label lblCaption;
public static string SelectedItem = null;
public static List<string> CheckedItems = null;
private TreeView treeView1;
private bool selectInvokesClose;


public Chooser()
{
InitializeComponent();
}

private Chooser(string Caption, bool FullScreen, bool SelectInvokesClose)
{
InitializeComponent();
CheckedItems = new List<string>();
SelectedItem = null;
this.selectInvokesClose = SelectInvokesClose;
this.lblCaption.Text = Caption;
this.mmOK.Enabled = false;

if (FullScreen)
{
this.WindowState = FormWindowState.Maximized;
this.FormBorderStyle = FormBorderStyle.None;
this.ControlBox = false;
this.MinimizeBox = false;
}
}

public Chooser(string Caption, string[] Items, bool FullScreen, bool SelectInvokesClose)
: this(Caption, FullScreen, SelectInvokesClose)
{
this.treeView1.BeginUpdate();
foreach (string s in Items)
this.treeView1.Nodes.Add(s);
this.treeView1.EndUpdate();
}

public Chooser(string Caption, string[] Items, bool FullScreen, bool CheckBoxes, bool SelectInvokesClose, bool CheckAll)
: this(Caption, Items, FullScreen, SelectInvokesClose)
{
this.treeView1.CheckBoxes = CheckBoxes;
if (CheckBoxes && CheckAll)
foreach (TreeNode node in this.treeView1.Nodes)
node.Checked = true;
if(CheckBoxes)
this.mmOK.Enabled = true; // don't require any user input
}

private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
this.mmOK.Enabled = true;
if (selectInvokesClose)
this.mmOK_Click(sender, EventArgs.Empty);
}

#region Windows Form Designer generated code

/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}


/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.mainMenu1 = new System.Windows.Forms.MainMenu();
this.mmCancel = new System.Windows.Forms.MenuItem();
this.mmOK = new System.Windows.Forms.MenuItem();
this.lblCaption = new System.Windows.Forms.Label();
this.treeView1 = new System.Windows.Forms.TreeView();
this.SuspendLayout();
//
// mainMenu1
//
this.mainMenu1.MenuItems.Add(this.mmCancel);
this.mainMenu1.MenuItems.Add(this.mmOK);
//
// mmCancel
//
this.mmCancel.Text = "Cancel";
this.mmCancel.Click += new System.EventHandler(this.mmCancel_Click);
//
// mmOK
//
this.mmOK.Text = "OK";
this.mmOK.Click += new System.EventHandler(this.mmOK_Click);
//
// lblCaption
//
this.lblCaption.Dock = System.Windows.Forms.DockStyle.Top;
this.lblCaption.Font = new System.Drawing.Font("Tahoma", 10F, System.Drawing.FontStyle.Bold);
this.lblCaption.Location = new System.Drawing.Point(0, 0);
this.lblCaption.Name = "lblCaption";
this.lblCaption.Size = new System.Drawing.Size(240, 27);
this.lblCaption.Text = "...";
//
// treeView1
//
this.treeView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.treeView1.Location = new System.Drawing.Point(0, 27);
this.treeView1.Name = "treeView1";
this.treeView1.ShowLines = false;
this.treeView1.ShowPlusMinus = false;
this.treeView1.ShowRootLines = false;
this.treeView1.Size = new System.Drawing.Size(240, 241);
this.treeView1.TabIndex = 12;
//
// Chooser
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.AutoScroll = true;
this.ClientSize = new System.Drawing.Size(240, 268);
this.ControlBox = false;
this.Controls.Add(this.treeView1);
this.Controls.Add(this.lblCaption);
this.KeyPreview = true;
this.Menu = this.mainMenu1;
this.MinimizeBox = false;
this.Name = "Chooser";
this.Text = "Choose Item";
this.Load += new System.EventHandler(this.Chooser_Load);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Chooser_KeyDown);
this.ResumeLayout(false);

}
#endregion

private void Chooser_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == System.Windows.Forms.Keys.Enter))
this.mmOK_Click(sender, EventArgs.Empty);
}

private void mmOK_Click(object sender, EventArgs e)
{
if (this.treeView1.SelectedNode != null)
Chooser.SelectedItem = this.treeView1.SelectedNode.Text;
if (this.treeView1.CheckBoxes)
foreach (TreeNode n in this.treeView1.Nodes)
if (n.Checked)
CheckedItems.Add(n.Text);

this.DialogResult = DialogResult.OK;
this.Close();
}

private void mmCancel_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}

private void Chooser_Load(object sender, EventArgs e)
{
this.treeView1.Focus();
this.treeView1.SelectedNode = null;
this.treeView1.AfterSelect += new TreeViewEventHandler(treeView1_AfterSelect);
}
}
}


Wednesday, 26 May 2010 15:51:34 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  .Net Compact

# Saturday, 19 September 2009
Hillwalking in the Lakeland Fells

Just back from a two week trip in the Lake District in England, what a discovery.  this photo was taken at sunrise at 500m on the last day.  unfortunately the first 10 days were mostly torrential rain, but it was worth it in the end. i want to go back next year.  i posted some more info on the trip at the wainwright society forum where i got some good advice before going.


Saturday, 19 September 2009 15:49:34 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  Outdoors

# Tuesday, 21 April 2009
Javascript dynamic anchor select menu
I got a request from a client for a 'mini' navigation menu to appear on a page to allow the user to 'jump' to the various sections of the page.  Maintaining a set of named anchor hyperlinks in a document (with a javascript-based select menu) is not really an option for someone who doesn't know HTML, which is most people who use content management.  In the wrong hands this creates more trouble than it's worth. 
so i started thinking. the documents in question are well structured, using paragraphs and headings, as enforced by the content management system.  i worked out this solution which is exactly what i need, a maintenance free javascript jump menu, that doesn't add clutter to the document with named anchors.  it assumes that the all H2 tags should be displayed as links in the menu.  the javascript iterates through the H2 tags and loads up the menu, with a ScrollTo function used when an item is selected.

here's a screenshot


The code for the HTML page:
<script src="/JumpMenu.js" type="text/javascript"></script>
<select id="jumpNavSelect" name="jumpNavSelect" onchange="JumpToHeading(this.selectedIndex)">
<option value="">On this page...</option>
</select>
and the JumpMenu.js file
var array;

function CreateAnchorMenu() {
array = document.getElementsByTagName("h2");
var src = document.getElementById('jumpNavSelect');
// iterate through all H2 headings, add dropdown items for each.
for (var i = 0; i < array.length; i++) {
var heading = array[i];
var text = heading.firstChild.nodeValue;
if (!text)
continue;
src[i+1] = new Option(text, i);
}
}

function JumpToHeading(HeadingIndex) {
if (HeadingIndex == 0)
return;
var heading = array[HeadingIndex-1];
ScrollToElement(heading);
}

function ScrollToElement(theElement) {
var selectedPosX = 0;
var selectedPosY = 0;
while (theElement != null) {
selectedPosX += theElement.offsetLeft;
selectedPosY += theElement.offsetTop;
theElement = theElement.offsetParent;
}
window.scrollTo(selectedPosX, selectedPosY);
}

window.onload = CreateAnchorMenu;

Tuesday, 21 April 2009 13:30:58 (GMT Daylight Time, UTC+01:00)  #    Comments [3]  .Net General | Asp.Net

# Tuesday, 24 March 2009
Asp.Net membership, correcting username case at login
if your application has users who like to log in as "JOE BLOGGS" or "joe bloggs" when their username is actually "Joe Bloggs", you might want to ensure that they login with the correct "case" of their username.  It can cause discrepancies if you refer to the current Identity.User in your web application, for example if you use the username anywhere in your database and run reports grouped on the username, you will get multiple records for each variation on the case of the username.  It is surprisingly unintuitive to solve this problem.  Firstly you would think that Asp.Net membership would take care of this itself.  Then you would think that you could determine the correct case of the username as follows:
protected void Login1_LoggedIn(object sender, EventArgs e)
{
string correctUsername = Membership.GetUser(this.Login1.Username).Username;
FormsAuthentication.SetAuthCookie(correctUsername , true);
}

but this doesn't work because the "Username" property of the MembershipUser object does not collect its value from the AspNetDB SQL database like you would expect, instead it is filled with whatever you pass it when loading the user, this must be a bug but i'm not bothered trying to convince MS.  instead, i came up with this solution below, to directly load the AspNetUser object from a Linq DataSource of the AspNetDb database (created using SqlMetal).

protected void Login1_LoggedIn(object sender, EventArgs e)
{
// correct the case of the username
string Username = this.Login1.UserName;
AspNetDb db = new AspNetDb();
MembershipUser memUser = Membership.GetUser(Username); // load the MembershipUser object to get the UserID
Aspnet_User aspnetUser = db.Aspnet_Users.SingleOrDefault(z => z.UserId == new Guid(memUser.ProviderUserKey.ToString()));
if(aspnetUser != null)
Username = aspnetUser.UserName;
FormsAuthentication.SetAuthCookie(Username, true);
}


Tuesday, 24 March 2009 16:38:48 (GMT Standard Time, UTC+00:00)  #    Comments [1]  Asp.Net

# Friday, 27 February 2009
Crystal Reports date format (in code)
Cstr(CDate({Table.Column}), "dd/MM/yyyy")


Friday, 27 February 2009 17:47:52 (GMT Standard Time, UTC+00:00)  #    Comments [0]  .Net General | Asp.Net