Thursday, 30 April 2009
Ruby Quiz
I often find that I need a little task to keep my programming mind happy, but often have trouble coming up with problems to solve. I stumbled across Ruby Quiz a few weeks ago, and I have used the ideas there, but have been creating solutions in C# rather than Ruby.
Wednesday, 29 April 2009
Server Side Click, CommandName and Command Argument on an ASP.Net TextBox
We had a requirement a work recently to provide support for a
The solution I came up with was to try and find a control that supported this functionality and that the server would think was a control of that type, but would be rendered in the browser as a
Rather than do all the hard work myself, I thought that the easiest way to create the rendering code was to get the
In order to not render the data part of the
Here is the final code...
TextBox
in an ASP.Net Web Forms application that posted back to the server when it was clicked on. We needed to support both the Click event style functionality and also the CommandName
- CommandArgument
functionality so that the TextBox
could be included in a DataGrid
and fire the DataGrid
's ItemCommand
event. It would not be necessary to read the value entered into the text box as it would be read only and be updated server side.The solution I came up with was to try and find a control that supported this functionality and that the server would think was a control of that type, but would be rendered in the browser as a
TextBox
. The best matching control was LinkButton
. LinkButton
provided all the server side functionality that I required, and little more, so I decided that I would subclass that control. Now all I had to do was make ASP render the control as a text box.Rather than do all the hard work myself, I thought that the easiest way to create the rendering code was to get the
LinkButton
to render itself to a dummy renderer, read in the string it rendered and then just change the bits I needed to. In order to get the control to look like a text box I have to change the element name to Input
and add a new attribute type="text"
. In order to get the value of the LinkButton
's Text property to display in the TextBox
I had to add value=""
. Finally to make the events fire when the TextBox
was clicked I had to assign the value of the href
attribute to the TextBox
's onclick
attribute. In order to get the events to fire when the user tabbed into the control I also added it to the onfocus
attribute.In order to not render the data part of the
LinkButton
in the ASP.Net page I overrode the RenderContents
method so that it did not do anything. Finally I removed all the re-useable code to another class so that I could use the technique again with other controls.Here is the final code...
public abstract class CustomLinkButton : LinkButton
{
protected abstract string GetInputType();
protected abstract void WriteControlSpecificAttributes(HtmlTextWriter writer);
public override void RenderBeginTag(HtmlTextWriter writer)
{
var builder = new StringBuilder();
using (var dummyWriter = new HtmlTextWriter(new StringWriter(builder)))
{
base.RenderBeginTag(dummyWriter);
var attributes = GetAttributes(builder.ToString());
foreach (var kvp in attributes)
{
if (kvp.Key == "href")
{
writer.AddAttribute("onClick", kvp.Value);
WritePostBackAttributes(writer, kvp.Value);
}
else
{
writer.AddAttribute(kvp.Key, kvp.Value);
}
}
writer.AddAttribute("type", GetInputType());
writer.AddAttribute("readonly", "readonly");
WriteControlSpecificAttributes(writer);
writer.RenderBeginTag("input");
}
}
protected virtual void WritePostBackAttributes(HtmlTextWriter writer, string hrefValue)
{
// do nothing
}
protected override void RenderContents(HtmlTextWriter writer)
{
// don't write anything
}
private Dictionary GetAttributes(string tag)
{
using (var reader = new XmlTextReader(tag, XmlNodeType.Element, null))
{
var result = new Dictionary();
reader.Read();
if (reader.MoveToFirstAttribute())
{
do
{
result[reader.Name] = reader.Value;
}
while (reader.MoveToNextAttribute());
}
return result;
}
}
}
public class NewTextBox : CustomLinkButton
{
protected override string GetInputType()
{
return "text";
}
protected override void WriteControlSpecificAttributes(HtmlTextWriter writer)
{
writer.AddAttribute("value", Text);
}
protected override void WritePostBackAttributes(HtmlTextWriter writer, string hrefValue)
{
writer.AddAttribute("onfocus", hrefValue);
}
}
Thursday, 23 April 2009
Including up to date Generated Code in a Rebuild
I recently came up against a problem where I had a pre-build event in a Visual Studio project that generated some code that was to be included when that project was built. While the code files were generated successfully the generated assembly always seemed to use the files generated for the previous build.
Most of the time this was not an issue as the generated code stayed the same, but if I changed one of the files that the generator used as a source, or the generator code itself I had to hit Rebuild twice in order for the new code to be picked up. It was as if Visual Studio was checking what files or versions of files were to be included before running the pre-build event. I tried some remedies suggested on the internet, but none of them worked; I always had to click Rebuild twice.
I reasoned that if a pre-build event did not work, perhaps I could use a post-build event on another project in the solution, and copy the results to the project I wanted them in. That way the code would be generated before Visual Studio got it’s mucking hands on it.
To reproduce this solution:
I used this procedure to generate a set of WCF Data and Service contracts based on some LinqToSql classes in a project that I am in the VERY EARLY stages of developing on sourceforge. I did not want to use the LinqToSql classes directly in the contract, so that the client did not need to reference the data layer’s assembly. Here is a link to the project page. http://sourceforge.net/projects/sandpiper
Most of the time this was not an issue as the generated code stayed the same, but if I changed one of the files that the generator used as a source, or the generator code itself I had to hit Rebuild twice in order for the new code to be picked up. It was as if Visual Studio was checking what files or versions of files were to be included before running the pre-build event. I tried some remedies suggested on the internet, but none of them worked; I always had to click Rebuild twice.
I reasoned that if a pre-build event did not work, perhaps I could use a post-build event on another project in the solution, and copy the results to the project I wanted them in. That way the code would be generated before Visual Studio got it’s mucking hands on it.
To reproduce this solution:
- Imagine the project you want the generated code to be compiled into is called RealProject
- Create another project in your solution. I chose a class library and called it CodeGenerator, but you could use any project type I guess.
- Put your generating code in the post-build event of the CodeGenerator project. My code was similar to the following:
CodeGeneratingApp.exe parameter1 parameter2 > “$(SolutionDir)RealProject\GeneratedCode.cs
- Build CodeGenerator
- Highlight RealProject in the Solution Explorer and Click the show all files button.
- Include GeneratedCode.cs in Real Project
- Right click RealProject in Solution Explorer and choose Project Dependencies
- Check the CodeGenerator project.
I used this procedure to generate a set of WCF Data and Service contracts based on some LinqToSql classes in a project that I am in the VERY EARLY stages of developing on sourceforge. I did not want to use the LinqToSql classes directly in the contract, so that the client did not need to reference the data layer’s assembly. Here is a link to the project page. http://sourceforge.net/projects/sandpiper
Wednesday, 15 April 2009
Dice Roller using LINQ
For my day job I'm a software developer at a company that produces telephone billing software. It's something I've done in the past, and I was lucky to get another job working in the same field. Having read a few posts about how useful and easy to read LINQ can be, I decided to take a quick look at writing a dice rolling utility using link to perform common dice rolling tasks.
Here is the code...
Here is the code...
using System;
using System.Collections.Generic;
using System.Linq;
namespace DiceUtils
{
public static class Dice
{
private readonly static Random random = new Random();
public static int Roll(int sides)
{
return random.Next(sides) + 1;
}
public static IEnumerable<int> Roll(int dice, int sides)
{
return Enumerable.Range(0, dice).Select(x => Roll(sides));
}
public static IEnumerable<int> Roll(int dice, int sides, int keep)
{
return Roll(dice, sides).AsQueryable().OrderByDescending(x => x).Take(keep);
}
}
}
Monday, 13 April 2009
Pendragon Resources
While I'm on the subject here is a link to some handy Pendragon resouces:
http://homepages.nyu.edu/~dp58/pendragon.htm
http://homepages.nyu.edu/~dp58/pendragon.htm
Creating Pendragon Characters
I last played Pendragon about 10 years ago, but after I met one of my old gaming friends that I hadn't seen for three or four years, at the local supermarket I was desparate to dig out my old rulebooks and see if I could remember the rules.
I remember from my playing days that we had trouble with character creation. If we used the points method every single character have maximum SIZ and close to maximum STR and CON, so every character also had minimal DEX and APP. If you use the random method the characters were very much underpowered as rolling 14d6 + 6 gives an average of 55 points, compared to the 60 of the points method and quite often resulted in unplayable characters.
I remebered that I once saw a system based on playing cards for creating d20 characters and I had a quick play arround to see if that were adaptable to Pendragon. The following system creates characters that have a stat total of 60. Nobody will have to play a character with a SIZ less than 13 or another stat less than 9 if they don't want to. It should also mean that not every character in the group has exactly the same stats.
Method:
I remember from my playing days that we had trouble with character creation. If we used the points method every single character have maximum SIZ and close to maximum STR and CON, so every character also had minimal DEX and APP. If you use the random method the characters were very much underpowered as rolling 14d6 + 6 gives an average of 55 points, compared to the 60 of the points method and quite often resulted in unplayable characters.
I remebered that I once saw a system based on playing cards for creating d20 characters and I had a quick play arround to see if that were adaptable to Pendragon. The following system creates characters that have a stat total of 60. Nobody will have to play a character with a SIZ less than 13 or another stat less than 9 if they don't want to. It should also mean that not every character in the group has exactly the same stats.
Method:
- Take the following cards from a standard deck of cards... 1 Ace (counts as 1), 3 2s, 4 3s, 3 4s, 2 5s and 3 6s.
- Set asside 2 of the 2s and this should leave you a deck of 14 cards, one card for each die rolled during a standard character creation.
- Shuffle the 14 cards together.
- Deal 2 cards to SIZ and three cards to each of the other stats in order.
- SIZ will equal the total of the two cards plus 6.
- The other stats will be equal to the total of the three cards dealt to them.
- Now the spare 2 2s are assigned to any stat as the player wishes, as long as no stat is increased above 18. they can be assigned to different stats or both to the same stat as desired.
- Cultural modifiers are now applied as normal and can take stats above 18 as usual.
Hello
Here is the first post of my new blog. I'm rather belatedly joining the blog community. I have decided to start a blog as I have had many ideas that I keep meaning to post on the internet, but have never gotten round to. My wife has also signed me up for FaceBook and I noticed that you can link to a blog from there. As FaceBook is not really the best place for posting RPG ideas and code snippets I thought that writting a blog would be better, and easier than maintaining my own website.
Subscribe to:
Posts (Atom)