TODO:
Have you ever wanted to change the Font of your Navigation bar text?
SOLUTION:
//Put this public override bool FinishedLaunching of AppDelegate
UITextAttributes titleTextAttributes = new UITextAttributes();
titleTextAttributes.Font = UIFont.FromName("Chalkduster", 20);
rootNavigationController.NavigationBar.SetTitleTextAttributes(titleTextAttributes);
NOTES:
In AppDelegate, put the lines of code above in your FinishedLaunching method. rootNavigationController is the root nav control you have declared in that class.
TODO:
Have you ever wanted to reseed an Identity column in your database?
SOLUTION:
DBCC CHECKIDENT (yourtablename, reseed, 1)
NOTES:
The above command will reset the identity to start at 1. You can set that to any value you would like.
TODO:
Have you ever wanted the 3rd Monay of the month, or some other similar scenario? Below is a method that will do this for you, as well as some sample calls to it.
int xDayOfMonth = GetNthDayOfMonth(2, System.DayOfWeek.Sunday); //get the 2nd Sunday of the current month
xDayOfMonth = GetNthDayOfMonth(5, System.DayOfWeek.Tuesday); //get the LAST tuesday of the current month
xDayOfMonth = GetNthDayOfMonth(3, System.DayOfWeek.Saturday); //get the third Saturday of the current month
SOLUTION:
public int GetNthDayOfMonth(int nth, DayOfWeek dayOfWeek)
{
int day = (int)dayOfWeek;
DateTime now = DateTime.Now; //get now, in case we span days
DateTime firstDayOfMonthDate = new DateTime(now.Year, now.Month, 1); //now get the first day of month
DayOfWeek firstDayOfWeek = firstDayOfMonthDate.DayOfWeek; //now get the day of week
int firstOfMonthDay = (int)firstDayOfWeek;
int returnDay = 0;
int x = (int)System.DayOfWeek.Sunday;
//now compare day to curr day (sunday==0 fyi)
if (firstOfMonthDay == day)
{
//the first day of the month is what we need, so do the simple math
returnDay = 1 + (7 * (nth - 1));
}
else if (firstOfMonthDay < day) //( ex: wed < thurs )
{
//ex. 3rd thurs of Feb 2012 - 1 + (7 *(3-1)) + (4-3) = 16 (16th day of month)
returnDay = 1 + (7 * (nth - 1)) + (day - firstOfMonthDay);
}
else //(firstday > day) ex: wed > mon )
{
//ex. 3rd mon of Feb 2012 - 1 + (7 *(3-1)) + (3+1) = 20 (20th day of month)
returnDay = 1 + (7 * (nth - 1)) + (firstOfMonthDay + day) + 1; //add one at end to fix 0 offset of DayOfWeek
}
//in this case we need to make sure we are not in an invalid date scenario, if so back it out by 7 days
if (nth == 5)
{
DateTime outDate;
DateTime.TryParse(String.Format("{0}-{1}-{2}", now.Year, now.Month, returnDay), out outDate);
//if it was bad, minus 7 and go
if (outDate == DateTime.MinValue || outDate == null)
returnDay -= 7;
}
return returnDay;
}
NOTES:
There are no notes on this topic.
TODO:
Have you ever wanted to show a custom Map Annotation on a Map using Monotouch for iPhone?
SOLUTION:
public override MKAnnotationView GetViewForAnnotation (MKMapView mapView, NSObject annotation)
{
if(!annotation.GetType().Equals(typeof(MyCustomAnnotation)) )
return null;
var anv = mapView.DequeueReusableAnnotation("myannotation");
if (anv == null)
{
anv = new MKAnnotationView(annotation, "myannotation");
anv.CanShowCallout = true;
anv.Image = UIImage.FromFile("Images/myannotation.png");
}
else
{
anv.Annotation = annotation;
anv.CanShowCallout = true;
}
//add a right accessory to show details if there are there and are not the same as the title...
if(!String.IsNullOrEmpty( ((MyCustomAnnotation)anv.Annotation).Details) &&
((MyCustomAnnotation)anv.Annotation).Details != ((MyCustomAnnotation)anv.Annotation).Title )
{
var accButton = UIButton.FromType(UIButtonType.DetailDisclosure);
accButton.Title (UIControlState.Normal);
anv.RightCalloutAccessoryView = accButton;
}
return anv;
}
NOTES:
So here I have created a custom MKAnnoatation class called MyCustomAnnotation. Basically if the type coming into GetViewForAnnotation() is not mine I am ignoring it. If it is mine, then I am assigning a custom image to it, and also adding a Right Accessory Button, iff the tite is not the same as the details, and details is not null or empty. You could show additional images too, if you create another class that inherits MyCustomAnnotations. For instance public class MyCustomAnnotation2 : MyCustomAnnotation. You can then check to see if that is the instance coming in, and assign an image accordingly. Hope this helps, and feel free to contact me for issues.
TODO:
Have you ever just wanted to show an alert dialog to the user, for instance if Location Services are not enabled?
SOLUTION:
using (UIAlertView alert = new UIAlertView ("Oops", "Location Service must be enabled", null, "OK", null))
{
alert.Show ();
}
NOTES:
There are no notes on this topic.
TODO:
Have you ever had issues with MonoDevelop not syncing with XCode. In my scenario I was renaming my namespaces in MonoDevelop, and forgot all about the Class.designercs files.
SOLUTION:
When refactoring, be sure that your partial classes have the same namspaces, Changing it in the View, and failing to do so in the designer.cs file will end up giving you the "Error Synchronizing" message, and cause changes in Xcode to not sync up.
NOTES:
There are I am sure other reason why this may happen, however in my scenario, this was 100% the issue / resolution.
TODO:
Have you ever gotten the dreaded message [ 'xxx' is a 'namespace' but is used like a 'type' ], even though you are using the fully qualified namespace? For Example I have a Class named ProcessManager in the namespace ProcessManagerService.ProcessManager. When I create a Console app, I try creating my object by saying:
ProcessManagerService.ProcessManager.ProcessManager pManager = new ProcessManagerService.ProcessManager.ProcessManager()
This statement will give the error above, when really I shouldn't.
SOLUTION:
In this case, if you look at the Properties of your project, you will most likely see the "Target Framework" is set to ".Net Framework 4 Client Profile". Change that to ".Net Framework 4", and your build error will go away.
NOTES:
Information on the .Net Framework 4 Client Profile can be found at http://msdn.microsoft.com/en-us/library/cc656912.aspx
TODO:
Have you ever had the dreaded, "Object does not exist...or permission denied error" when you try to enable or disable a trigger?
SOULTION:
--get the user executing the SQL
select USER_NAME()
--now grant ALTER on that table to that user
GRANT ALTER ON Table TO User
NOTES:
This becomes useful when you are trying to disable a trigger in a Stored Procedure or another Trigger.
TODO:
Have you ever wanted to write to a seperate log file per class for instance? In my case, I was running a Start() method of a class in a thread, and I was ending up with log messages in the single log file in an order that was really hard to follow. I wanted to write each class to it's own log file, and also ensure it was Thread safe while doing so. I was a little shocked at the lack of example out there on this topic, so below I have included a log class that wraps the log4net calls, and allows you to do the above.
SOLUTION:
using System;
using System.Collections.Generic;
using System.Text;
using log4net;
using log4net.Core;
using log4net.Config;
using log4net.Layout;
using log4net.Repository;
using log4net.Appender;
using log4net.Repository.Hierarchy;
namespace DevelopersAlley.Logging
{
public class ThreadSafeLogger
{
private const string _LOGNAME = "LogName";
static readonly object _locker = new object();
private ILog _logger;
/// <summary>
/// Allow a log file name to be passed in
/// </summary>
/// <param name="className"></param>
/// <param name="LogFileName"></param>
public ThreadSafeLogger(string ClassName, string LogPath)
{
if (!String.IsNullOrEmpty(LogPath))
{
//clean up path
if (!LogPath.EndsWith("\\"))
LogPath += "\\";
}
else
LogPath = "";
//make the nice log path
LogPath = String.Format("{0}{1}.log", LogPath, ClassName);
lock (_locker)
{
log4net.ThreadContext.Properties[_LOGNAME] = ClassName;
_logger = LogManager.GetLogger("Root");
if (!_logger.Logger.Repository.Configured)
XmlConfigurator.Configure();
//add the appender and set the filter now...
AddAppender(ClassName, CreateFileAppender(ClassName, LogPath));
}
}
#region LOG4NET UTILITIES
/// <summary>
/// Add an appender
/// </summary>
/// <param name="LoggerName"></param>
/// <param name="Appender"></param>
private void AddAppender(string LoggerName, log4net.Appender.IAppender Appender)
{
log4net.ILog log = log4net.LogManager.GetLogger(LoggerName);
log4net.Repository.Hierarchy.Logger l = (log4net.Repository.Hierarchy.Logger)log.Logger;
l.AddAppender(Appender);
}
/// <summary>
/// Find a named appender already attached to a logger
/// </summary>
/// <param name="appenderName"></param>
/// <returns></returns>
public log4net.Appender.IAppender FindAppender(string AppenderName)
{
foreach (log4net.Appender.IAppender appender in log4net.LogManager.GetRepository().GetAppenders())
{
if (appender.Name == AppenderName)
return appender;
}
return null;
}
/// <summary>
/// Create an appender
/// </summary>
/// <param name="name"></param>
/// <param name="fileName"></param>
/// <returns></returns>
public log4net.Appender.IAppender CreateFileAppender(string ClassName, string FileName)
{
log4net.Appender.RollingFileAppender appender = (log4net.Appender.RollingFileAppender)FindAppender(ClassName);
if (appender != null)
return appender;
appender = new log4net.Appender.RollingFileAppender();
appender.Name = ClassName;
appender.File = FileName;
appender.AppendToFile = true;
appender.MaximumFileSize = "10MB";
appender.MaxSizeRollBackups = 5;
appender.RollingStyle = RollingFileAppender.RollingMode.Size;
appender.StaticLogFileName = true;
//// add the filter for the log source
log4net.Filter.PropertyFilter filter = new log4net.Filter.PropertyFilter();
filter.Key = _LOGNAME;
filter.StringToMatch = ClassName;
filter.AcceptOnMatch = true;
//add deny all filter
log4net.Filter.DenyAllFilter filterDeny = new log4net.Filter.DenyAllFilter();
appender.AddFilter(filter);
appender.AddFilter(filterDeny);
log4net.Layout.PatternLayout layout = new log4net.Layout.PatternLayout();
layout.ConversionPattern = "%d [%t] %-5p %c - %m%n";
layout.ActivateOptions();
appender.Layout = layout;
appender.ActivateOptions();
log4net.Config.BasicConfigurator.Configure(appender);
return appender;
}
#endregion
#region INFO LOGGING
/// <summary>
/// Log a message to a particular log name
/// </summary>
/// <param name="messageFormat"></param>
/// <param name="classname"></param>
public void LogInfo(string MessageFormat, string ClassName)
{
lock (_locker)
{
log4net.ThreadContext.Properties[_LOGNAME] = ClassName;
if (_logger.IsInfoEnabled)
_logger.Info(MessageFormat);
}
}
#endregion
#region DEBUG LOGGING
/// <summary>
/// Log debug message to a file
/// </summary>
/// <param name="messageFormat"></param>
/// <param name="classname"></param>
public void LogDebug(string MessageFormat, string ClassName)
{
lock (_locker)
{
log4net.ThreadContext.Properties[_LOGNAME] = ClassName;
if (_logger.IsDebugEnabled)
_logger.Debug(MessageFormat);
}
}
#endregion
#region ERROR LOGGING
/// <summary>
/// Logs an error message to a specific log
/// </summary>
/// <param name="messageFormat"></param>
/// <param name="classname"></param>
public void LogError(string MessageFormat, string ClassName)
{
lock (_locker)
{
log4net.ThreadContext.Properties[_LOGNAME] = ClassName;
if (_logger.IsErrorEnabled)
_logger.Error(MessageFormat);
}
}
#endregion
}
}
NOTES:
- IMPORTANT** - in your app config, you now only need empty log4net node. Having any appenders in this node will throw things off, and you will end up with logs getting mixed up.
<log4net debug="true"></log4net>
- This creates appenders on the fly, and sets a PropertyFilter by the ClassName value that I passed in.
- Before the log event, you can see I set a property _LOGNAME, to ClassName. By setting this property, the filter will now only allow events to go to that Appender, because we applied a PropertyFilter to the Appender when we created it.
- I added locking to ensure Thread safety (may be overkill)
- To use, just call this code.
protected ThreadSafeLogger _Logger = null;
_Logger = new ThreadSafeLogger ("MyClassName", "C:\\logs");
- You will end up with a log file named C:\logs\MyClassName.log
- If you do #5 in each class with a different class name, you will end up with a log per class.
- Enjoy!
TODO:
Have you ever wanted to create a thread, and pass a parameter to it when it starts?
SOLUTION:
//This code creates the thread, and starts it with a parameter
Thread myThread = new Thread(new ParameterizedThreadStart(MyMethodtoCall)); //create our job thread
myThread.Start(jobStepsToRun); //start it now, passing in our parameter
//This method will be use in the ParameterizedThreadStart call
private void MyMethodtoCall(object myPassedParameter)
{
//here you can access your parameter and use it
}
NOTES:
There are no notes on this topic.