Spring Vacation!

March 20th, 2014 Comments

image

Categories: Daily Grind Tags:

Extending DropDownList: Add EmptyDataTemplate Support

May 8th, 2013 Comments

This is a small but handy extension of the standard .NET DropDownList control in order to support an EmptyDataTemplate.  The EmptyDataTemplate concept is used in other places to display some content when the bound datasource returns no results. It’s unfortunately not natively provided in the DropDownList, but I’ve found it to be very helpful.

I confess that this (at present) does not function fully like the normal EmptyDataTemplate usage, which is written as a child control. Rather, it’s simply an additional parameter.  As such, it will really only support text.

[Read More]

Categories: Code Tags:

A Day in the Life of a Bi-Vocational Pastor.

January 7th, 2013 Comments

 

7am.   Wake up to the sound of Andrew yelling, “Ezra’s on the stairs!”  Move in great haste to save the teetering 11-month old at the top of the stairs.  Let the day begin!

7:10. Breakfast. Feeding the baby and trying to figure out to cut the crust off an English Muffin while Julie pulls out their clothes and lunches for the day.

7:40. Load kids into the car and begin my morning job as bus driver. Andrew is crying because he can’t find mittens. Amelia reminds him he has mittens tied into his coat. Which he is wearing. Buckle them in and run back to the house to get Amelia’s snack – an orange. Give to Amelia. Andrew starts crying that he wants an orange.  Turn up the radio.

7:55. Unbuckle and walk both kids into Amelia’s school. 17 seconds later, return and buckle Andrew back into his seat.

8:10. Enough time between schools to run an errand. Today it’s going to the bank.

8:20. Arrive at Andrew’s school. Still a little early. Check email. Delete anything important.

8:25. Pretend to be an elevator to get Andrew out of the car. We race to the door. He wins. Again.

8:30. He’s changed into school shoes and I lift him up – as I do every school day – so he can peer into the classroom before we enter. “What do you see?” I ask. He replies, without fail, “Teachers and friends!” We enter and exchange “smooshie” hugs until he’s ready to rock.

8:45. Back in the car. Notice a missed call from work. Call back and spend a few minutes answering questions for a co-worker. Take a deep breath and listen to NPR for a few minutes before launching into the rest of the day.

9:00. Arrive home. Load up laptop and other accessories into the car. I’ll be working from the church today, and decide to bring over my wide-screen monitor to try out the docking station. Refill coffee. Shovel out mailbox. Bring in mail. Julie asks me to return dishes to the church leftover from pot luck yesterday. Clean off my car from the previous days’ snow flurry using a dish.

9:40. Finally make it to the office, which is 200ft away from the house. Unload the car and spend a few minutes organizing, hooking up the monitor, pushing buttons on the docking stations until it lights up.

9:55. Take another call for work. Save the world. Again.

10:00. Work! Write up and send out a weekly Monday-morning status report for a client. Exchange a quick half-dozen emails with a co-worker concerning an open work item. While exchanging emails an additional request comes in which takes precedence. Drop everything and shift gears.

11:00. Julie drops by to say hi (and pick up the credit card) before going grocery shopping. I take advantage of the break to go get a coffee at Freshies.

11:15. Work, take 2. Database backups, restores, and updating data from an excel spreadsheet.

12:00. Take a break to call Time Warner and cancel my home phone service. We haven’t even plugged it in since we arrived in Ellsworth 8 months ago. That $35 a month will help to cover my new taxes.

12:40. Pull out year-end donation reports which require my signature before being delivered. Review and sign each one. Humbled and grateful for the generosity and sacrifice of many. I sign my own, not really sure why.

1:00. Phone call from a lay leader at church. Discuss the previous day’s service and direction of the coming week – TBD.

1:15. Head home for lunch and my daily ritual of facilitating Andrew’s afternoon nap. Julie heats up leftovers for me while I read to Andrew. I relax and watch Millionare with Julie while eating lunch. I share the joy of being on the phone with Time Warner for an hour to cancel the phone service. She suggests cancelling cable as well. I suggest she call them.

2:00. Shovel more snow out back and bring in a couple loads of firewood.

2:20. Alerted that we may have accidentally taken home a pair of boots from one of Amelia’s friends who have the same style – and size – as Amelia. Unsuccessfully scour the shoe bin for anomalous boots.

2:30. Drive out to pick up Amelia while Julie stays home with napping kids. Greet other parents and discuss missing boot  situation. Boots are discovered at school. Day is saved. Amelia and I get back in the car and drive home.

3:00. Work, take 3. Take a couple calls, answer a couple emails, run some more database jobs.

4:00. Head home to bring in one more load of firewood while there is daylight.

4:05. Call former Youth Pastor who started his new job today.

4:10. Pick up cake from the store which I had ordered – and then forgot – for the Youth Pastor’s going away party.

4:25. Back in the office to wrap up a few things and close down shop for the day. Bring out bags of trash to the dumpster and discover bits of yesterday’s pot luck surrounding the dumpster, thanks to some animal which had got in. Clean up.

5:00. Walk through the door just as Andrew is waking up from his nap.

5:15. Thirty minute phone call with the church treasurer. End-of-year taxes, bills, home heating strategy, sicknesses, and fake Christmas trees.

6:00. Dinner! Amelia drops hers on the way to the table and bursts into tears.

6:15. Amelia stops crying.

7:00. Begin bedtime routine, slightly later then usual. Pajamas, teethbrushing, read books. Amelia is reading a version of “David and Goliath” to Ezra while I read “Just go to bed!” (appropriately) to Andrew.

9:00. House is quiet. Write a blog post.

10:45. Finish blog post and prep for board meeting tomorrow.

Categories: Daily Grind, Family Tags:

Welcome Home!

August 10th, 2012 Comments

A couple of significant changes have been happening in the Donahue house. I don’t frequently post about family-related activity (I don’t post frequently at all) as it is mostly covered over at Donahue Happenings but here are a few things which are worth covering!

Meet Ezra.

Ezra Joseph Donahue was born January 20th in Lewiston, ME. At six months old, and is as big as his 1-year-old peers. I call him “The Large One” which is mostly in light of a nickname I picked up from Evan Desjardins – supposedly in light of my affection for Dunkin’ Donuts, but I don’t ask questions. Once again it’s proven true that “all children are different” as “Tres” is altogether unlikely his older brother and sister in their infancy. I could bore you with details of birth weight and size and time and eye color and percentage of birth weight composed of hair – but here is the important fact: He completes our family. We have a really special sense of togetherness and closeness that is nothing like what I’ve felt before. Andrew and Amelia absolutely love Ezra. When they are not watching Spider-Man or Avatar: The Last Airbender, they are smiling and tickling and playing with Ezra.

Within a couple weeks of Ezra’s birth we also welcomed my niece Lilliana Kathleen (who visited her American family recently!) and the passing of my Nana, Kathleen Brydon, as well as the passing of Julie’s grandfather Ira “Joe” Berry. This was a highly emotional time for our family and many helped us through it.

Pastor, Ellsworth Church of the Nazarene

Following the Call of God, which it could only be at this tumultuous time in our lives, we packed up the fam and moved to Downeast Maine as Pastor of the Ellsworth Church of the Nazarene. This is truly a new chapter in our lives, and its still overwhelming – even 5 months into it – but God has been good and both the churches at Ellsworth and Lisbon Falls have been very gracious to us.  It has been tremendously heart-breaking to part ways with students and families that I have LOVED for four years – but I am very grateful that I am moving only a couple hours away and still get to see them around.  I have been surprised by visits from Sandi Wood and Dustin, Robert, Melissa, and Kristen at district events, and have seen Jordan (briefly!) at teen camp and kids camp.  I hear reports of Ben and Meagan who are stepping up and serving in Children’s Ministry. I still see Erlene everywhere I go!! Rick and Janice and the whole family came up to visit one weekend and I was also able to see them recently at camp.

As we came off the 50-foot truck which moved us here, we were welcomed by a large banner in the parsonage reading, “Welcome Home!” and signed by many in the church.  And so we turn the page into a new chapter of our lives – with three kids, 2 of which will be in school in just a few short weeks, a new role for me serving in ministry, a new location to explore and new families to meet and to love . Welcome home.

Categories: Daily Grind, Family Tags:

Festival of Life 2012

March 15th, 2012 Comments

image

Categories: Daily Grind Tags:

Extending DataControlField – EditableButtonField

January 14th, 2012 Comments

It turns out that once you start extending DataControlField, you never turn back.  I have discovered joy in reducing code duplication and creating reusable components by converting common GridView tasks into new DataControlFields. Here’s another fun one: EditableButtonField.

A “normal” ButtonField is a read-only control which has no built-in behavior when the row is being edited.  With the EditableButtonField control, it will convert to a TextBox and provide immediate access to the DataTextField element.  Nifty!

Note that this control simply extends ButtonField rather than extending the full DataControlField.  Also note that I am assuming a ButtonType of “Link” and this would probably explode into itty bitty bits if you tried a Button.

<code>

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace JoeDonahue.resources {
public class EditableButtonField : ButtonField {

private Boolean inEditMode;

public override void InitializeCell(DataControlFieldCell cell,
DataControlCellType cellType, DataControlRowState rowState, int rowIndex) {
base.InitializeCell(cell, cellType, rowState, rowIndex);

switch (cellType) {
case DataControlCellType.DataCell:
this.InitializeDataCell(cell, rowState);
break;
case DataControlCellType.Footer:
this.InitializeFooterCell(cell, rowState);
break;
case DataControlCellType.Header:
this.InitializeHeaderCell(cell, rowState);
break;
}
}

protected void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState) {

cell.DataBinding += new EventHandler(OnDataBindField);

this.inEditMode = (rowState & (DataControlRowState.Edit | DataControlRowState.Insert)) != 0;

if (inEditMode) {
TextBox t = new TextBox();
cell.Controls.Clear();
cell.Controls.Add(t);
} else {
// Default behavior is OK
}
}

protected void InitializeHeaderCell(DataControlFieldCell cell, DataControlRowState rowState) {
}

protected void InitializeFooterCell(DataControlFieldCell cell, DataControlRowState rowState) {
}

protected virtual void OnDataBindField(object sender, EventArgs e) {
TableCell cell = (TableCell)sender;
IDataItemContainer container = (IDataItemContainer)cell.NamingContainer;
object boundvalue = GetBoundValue(container);
String selectedValue = boundvalue.ToString();

/* Set the corresponding text or selectedValue */
if (inEditMode) {
object dataItem = DataBinder.GetDataItem(container);
boundvalue = DataBinder.GetPropertyValue(dataItem, DataTextField);
selectedValue = boundvalue.ToString();

TextBox t = (TextBox)cell.Controls[0];

if (selectedValue != null && selectedValue.Length > 0)
t.Text = selectedValue;

} else {
LinkButton l = (LinkButton)cell.Controls[0];
l.Text = selectedValue;
}

}

object GetBoundValue(IDataItemContainer controlContainer) {
object dataItem = DataBinder.GetDataItem(controlContainer);
return DataBinder.GetPropertyValue(dataItem, DataTextField);
}

public override void ExtractValuesFromCell(System.Collections.Specialized.IOrderedDictionary dictionary, DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly) {

base.ExtractValuesFromCell(dictionary, cell, rowState, includeReadOnly);

this.inEditMode = (rowState & (DataControlRowState.Edit | DataControlRowState.Insert)) != 0;

string value = null;

if (cell.Controls.Count > 0) {
Control control = cell.Controls[0];
if (control == null)
throw new InvalidOperationException(“The control cannot be extracted”);

if (inEditMode)
value = ((TextBox)control).Text;
else
value = ((LinkButton)control).Text;

}

if (dictionary.Contains(this.DataTextField))
dictionary[this.DataTextField] = value;
else
dictionary.Add(this.DataTextField, value);
}
}

}

</code>

 

Categories: Code, Daily Grind Tags:

Now Using Gmail Tablet & iPad Interface

December 1st, 2011 Comments

I use a Samsung Netbook with greater frequency, and have been really annoyed with the 3-pane look which includes a Chat section which I don’t even use. The alternative: Use the Gmail Interface which has been optimized for small screens.

Initial research recommended changing the User Agent String, which is both difficult (or not possible, depending on your browser) and unnecessary. The following link works just as well:

https://mail.google.com/mail/mu/mp/864/

This has not been optimized for all browsers, so use at your own risk.

Categories: Daily Grind Tags:

Custom DataControlField containing DropDownList

November 29th, 2011 Comments

While the idea is far from new (and can be seen in various implementations here, here, and here), every example I had found fell short of being exactly what I was looking for. My requirements, briefly, were:

  • Call a custom DataControlField from within a DetailsView
  • Do so from the ASP, not programmatically in the code-behind
  • Display a Label in View mode, but display a DropDownList in Edit Mode
  • The DropDownList must be tied to a SQLDataSource
  • The Update event, clearly, should save the selected value
  • Intellisense Integration. Because it gives me warm fuzzies.

Why?

Among the many variations uncovered above, one plaguing question kept arising – Why? This can easily be done by simply using a TemplateField. My answer is: Frequency.
This is not a once-in-a-lifetime requirement. I use this functionality – a lot. And while I appreciate the flexibility of the TemplateField, it is kind of annoying to me that I have to keep re-writing the same lines of code over-and-over again every single page I want to slap a DropDownList in a DetailsView. The DRY (Don’t Repeat Yourself) principle forced me over the edge.

Introducing… The DropDownField

While I expect to be revising both this page and the code as it is used out in the wild, I’ll be keeping this page updated both with my findings and any feedback I received.

The ASP Code

This run-of-the-mill DetailsView is bound to a SQLDataSource, as is the source for the DropDownList.

<res:DropDownField HeaderText=”Status” DataSourceID=”StatusData” DataTextField=”status” DataValueField=”status” />

The prefix for the control is “res”, which is defined in the web.config.

<system.web>

<pages>
<controls>
<add assembly=”JoeDonahue” namespace=”JoeDonahue.resources” tagPrefix=”res” />
</controls>
</pages>
</system.web>

DropDownField.cs

  • revision 2 – Updated 11/30/2011
  • revision 3 – Updated 07/26/2012

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace JoeDonahue.resources {
public class DropDownField : DataControlField {

public String DataTextField {
get {
object dataTextField = ViewState["DataTextField"];
if (dataTextField != null) {
return dataTextField.ToString();
}
return string.Empty;
}
set {
this.ViewState["DataTextField"] = value;
}
}

public string DataValueField {
get {
object dataValueField = ViewState["DataValueField"];
if (dataValueField != null) {
return dataValueField.ToString();
}
return string.Empty;
}
set {
this.ViewState["DataValueField"] = value;
}
}

public String DataSourceID {
get {
object dataSourceID = ViewState["DataSourceID"];
if (dataSourceID != null) {
return dataSourceID.ToString();
}
return string.Empty;
}
set {
this.ViewState["DataSourceID"] = value;
}
}

public string SelectedValue {
get {
object selectedValue = ViewState["selectedValue"];
if (selectedValue != null) {
return selectedValue.ToString();
}
return string.Empty;
}
set {
this.ViewState["selectedValue"] = value;
}
}

private Boolean inEditMode;

/** Methods **/

protected override DataControlField CreateField() {
return new DropDownField();
}

public override void InitializeCell(DataControlFieldCell cell,
DataControlCellType cellType, DataControlRowState rowState, int rowIndex) {
base.InitializeCell(cell, cellType, rowState, rowIndex);

switch (cellType) {
case DataControlCellType.DataCell:
this.InitializeDataCell(cell, rowState);
break;
case DataControlCellType.Footer:
this.InitializeFooterCell(cell, rowState);
break;
case DataControlCellType.Header:
this.InitializeHeaderCell(cell, rowState);
break;
}
}

protected void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState) {

cell.DataBinding += new EventHandler(OnDataBindField);

this.inEditMode = (rowState & (DataControlRowState.Edit | DataControlRowState.Insert)) != 0;

if (inEditMode) {
DropDownList ddl = new DropDownList();
ddl.ID = this.DataTextField;
ddl.DataSourceID = this.DataSourceID;
ddl.DataTextField = this.DataTextField;
ddl.DataValueField = this.DataValueField;
cell.Controls.Add(ddl);
} else {
Label l = new Label();
cell.Controls.Add(l);
}
}

protected void InitializeHeaderCell(DataControlFieldCell cell, DataControlRowState rowState) {
}

protected void InitializeFooterCell(DataControlFieldCell cell, DataControlRowState rowState) {
}

protected virtual void OnDataBindField(object sender, EventArgs e) {
TableCell cell = (TableCell)sender;
IDataItemContainer container = (IDataItemContainer)cell.NamingContainer;
object boundvalue = GetBoundValue(container);
String selectedValue = boundvalue.ToString();

/* Set the corresponding text or selectedValue */
if (inEditMode) {
object dataItem = DataBinder.GetDataItem(container);
selectedValue = DataBinder.GetPropertyValue(dataItem, DataValueField).ToString();
DropDownList ddl = (DropDownList)cell.Controls[0];
ddl.SelectedValue = selectedValue;
} else {
Label l = (Label)cell.Controls[0];
l.Text = selectedValue;
}

}

object GetBoundValue(IDataItemContainer controlContainer) {
object dataItem = DataBinder.GetDataItem(controlContainer);
return DataBinder.GetPropertyValue(dataItem, DataTextField);
}

public override void ExtractValuesFromCell(System.Collections.Specialized.IOrderedDictionary dictionary, DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly) {

base.ExtractValuesFromCell(dictionary, cell, rowState, includeReadOnly);

string value = null;

if (cell.Controls.Count > 0) {
Control control = cell.Controls[0];
if (control == null)
throw new InvalidOperationException(“The control cannot be extracted”);
value = ((DropDownList)control).SelectedValue;
}

if (dictionary.Contains(this.DataValueField))
dictionary[this.DataValueField] = value;
else
dictionary.Add(this.DataValueField, value);
}
}
}

Helpful Resources

The following links were really helpful in accomplishing this. Thanks!

Categories: Code Tags:

Family Vacation 2011 – Day 2

November 26th, 2011 Comments

image

After a strange (not not unusual) night which resulted with all 4 of us sleeping together, I woke up with the roosters at 4:30am, unable to return to sleep.  I learned a few things about roosters that morning: they don’t just crow once and be done with it; They continue to do so.  A lot.  So me and the roosters chilled out and played games on my phone for a couple hours.  Welcome to the first full day of vacation!

About 6 I crawled back into bed with the fam, and Andrew was starting to wake up.  By 6:30 we had woken up the rest of the house, and it was as comical as it was sad.  Not everyone are early birds like us, but our gracious hosts laughed with us, put on the coffee, and took us out back to greet the chickens… who were still asleep.  This was a first at the Murphy home: Waking up before the chickens.  We stood outside the roost, beckoning them out, but had no takers for several minutes.  Finally one brave chicken came out to be chased by Andrew, and the rest followed.

This was the first of many blessings of the day and has convinced me that the best way to spend vacation, if at all possible, is with friends.  We easily could have picked a destination with a hotel for a night on the way to break up the trip, but instead we had this self-contained mini-adventure which took us into parts of Lynchburg that will not show up on any website or advertisement.  But it was places where people are living their lives, sharing, and in community together; Where the Spirit reigns instead of touristy consumerism and entertainment.

After feeding the chickens and a pancake breakfast, we followed Carolyn over to her brother’s home, and visited with him and their friends Anita, Drew & fam, who we had met once before when they visited Maine. Another trip led us to a place where Kyle is building a home, log-cabin style.  He is still “timberframing” if I recall the word correctly, and the project is true to the vision. As Care led us around the area, she put it this way: “Our faith has been shaped by the restoration of things which have been abused or broken.”

{If you only read that quote once, you’ll need to stop and go back.}

And so they build a home on a stretch of land which has been abandoned and dormant for years, while others look for the latest in real-estate development zones. They cherish community and life together where others build fences.

As we walked around the area, we stumbled across a group of half-a-dozen goats, pictured above with Andrew.

With that, we had to gather up the children and hit the road.  Another 5 or 6 hours of driving awaited us, but it was another uneventful drive and we checked into our condo just outside Myrtle Beach, South Carolina by 5pm. We unpacked, completed an initial review of the playground, and settled in for the night, exhausted, but glad for the journey so far and looking forward to the day ahead.

Family Vacation 2011 – Day 1

November 25th, 2011 Comments

image

We joined the masses of Americans getting up in the early hours of Black Friday as we hit the road for our family vacation to Myrtle Beach, South Carolina.  Even Andrew was wide awake at 2:30am as we loaded the last items into the car (including not ONE hunting bow, but TWO!) and set out. Julie had gone to bed early the night before in order to take the first leg of the trip while I set out on 2 missions which would ultimately fail: a charger for the pump to an air mattress which ended being the wrong kind and nearly catching fire and a trip to Walmart which would NOT open at 10pm as advertised; By 10:15 I got the drift and went home for a nap.

The way was sure (with some help from Toby Levesque) and the gas tank was full.  First stop: Lynchburg, Virginia!

The first 14 hours were pretty uneventful, and we made it to the Murphy’s home just in time to eat dinner together and greet Kyle (the “daughter-stealer” as Toby likes to call him) and Jeremy as they returned, dejected from a full day of deer-hunting in which no deer received the memo.

While still early in our adventure, our primary reason for traveling South in the first place was everything I could have wanted. The kids played with Sparrow while Julie and I sat with Care, Kyle and Jeremy just to talk, laugh,to share an evening and a pot of coffee (and apple pie!) together. After the usual negotiations to determine sleeping arrangements, we turned in for the night, only marginally aware that it was only 8:30pm.