If you've spent any time with Silverlight, you've probably used it with a Web Service (ASMX or WCF, either one). And the first thing that jumps out at you is the fact that Silverlight does not and in fact cannot generate synchronous methods to call the web methods. In stead of a method called GetData that returns a value, you have a GetDataAsync method and a GetDataCompleted handler, to which the return value will be in the EventArg parameter.
This is not a bad thing. I don't particularly want a plugin blocking the browser's UI thread with a long-running synchronous call. In fact, I've read (somewhere, can't find the reference) that this is the reason that MS didn't allow Silverlight to do synchronous calls.
However, there are times when you need to do multiple calls, and then have something happen when they are all done. You can't trust that calls will finish in the order that you start them in, because these calls can run simultaneously. There are a few options to do this. I'll show you two examples. Article continues after the jump.
Maybe some code, maybe some observations, maybe some complaining.
Wednesday, September 1, 2010
Monday, August 30, 2010
Trimming/rounding a date time. Floors and ceilings.
Well, first, credit where credit is due. I found this on StackOverflow and only slightly modified it. But it's too good not to share.
This code will let you "round" a date time to any given interval. You can get the floor or ceiling, or do a traditional round.
Here's the code:
Here's a simple example using Floor:
And here's the output:
This code will let you "round" a date time to any given interval. You can get the floor or ceiling, or do a traditional round.
Here's the code:
public static class Extensions
{
public static DateTime Floor(this DateTime date, TimeSpan span)
{
if (span == TimeSpan.FromMinutes(0))
return date;
long ticks = date.Ticks / span.Ticks;
return new DateTime(ticks * span.Ticks);
}
public static DateTime Ceil(this DateTime date, TimeSpan span)
{
if (span == TimeSpan.FromMinutes(0))
return date;
long ticks = (date.Ticks + span.Ticks - 1) / span.Ticks;
return new DateTime(ticks * span.Ticks);
}
public static DateTime Round(this DateTime date, TimeSpan span)
{
if (span == TimeSpan.FromMinutes(0))
return date;
long ticks = (date.Ticks + (span.Ticks / 2)) / span.Ticks;
return new DateTime(ticks * span.Ticks);
}
}
Here's a simple example using Floor:
DateTime dt = new DateTime(2010, 8, 29, 15, 26, 23);
Console.WriteLine("Floor:");
Console.WriteLine(dt.Floor(TimeSpan.FromSeconds(0)));
Console.WriteLine(dt.Floor(TimeSpan.FromMinutes(1)));
Console.WriteLine(dt.Floor(TimeSpan.FromMinutes(5)));
Console.WriteLine(dt.Floor(TimeSpan.FromMinutes(10)));
Console.WriteLine(dt.Floor(TimeSpan.FromMinutes(60)));
Console.WriteLine();
Console.WriteLine("Ceil:");
Console.WriteLine(dt.Ceil(TimeSpan.FromSeconds(0)));
Console.WriteLine(dt.Ceil(TimeSpan.FromMinutes(1)));
Console.WriteLine(dt.Ceil(TimeSpan.FromMinutes(5)));
Console.WriteLine(dt.Ceil(TimeSpan.FromMinutes(10)));
Console.WriteLine(dt.Ceil(TimeSpan.FromMinutes(60)));
Console.WriteLine();
Console.WriteLine("Round:");
Console.WriteLine(dt.Round(TimeSpan.FromSeconds(0)));
Console.WriteLine(dt.Round(TimeSpan.FromMinutes(1)));
Console.WriteLine(dt.Round(TimeSpan.FromMinutes(5)));
Console.WriteLine(dt.Round(TimeSpan.FromMinutes(10)));
Console.WriteLine(dt.Round(TimeSpan.FromMinutes(60)));
Console.ReadKey();
And here's the output:
Floor: 8/29/2010 3:26:23 PM 8/29/2010 3:26:00 PM 8/29/2010 3:25:00 PM 8/29/2010 3:20:00 PM 8/29/2010 3:00:00 PM Ceil: 8/29/2010 3:26:23 PM 8/29/2010 3:27:00 PM 8/29/2010 3:30:00 PM 8/29/2010 3:30:00 PM 8/29/2010 4:00:00 PM Round: 8/29/2010 3:26:23 PM 8/29/2010 3:26:00 PM 8/29/2010 3:25:00 PM 8/29/2010 3:30:00 PM 8/29/2010 3:00:00 PM
Tuesday, August 24, 2010
Finding the calling method.
I've been tasked with writing a logging component of a current application we're working on. My co-worker provided me with a snippet of code that has proven to be quite useful:
I'm getting the third frame, because the method is two deep in the logger code, but you can use whatever number necessary to get the right frame. This gives you the whole Fully.Qualified.Namespace.Class.MethodName, which can be quite useful.
using System.Diagnostics; using System.Reflection; . . . //dig through the stack trace to find the calling method StackTrace stackTrace = new StackTrace(); //since this is two methods removed from the caller, go two deep StackFrame stackFrame = stackTrace.GetFrame(2); MethodBase methodBase = stackFrame.GetMethod(); string caller = methodBase.ReflectedType + "." + methodBase.Name;
I'm getting the third frame, because the method is two deep in the logger code, but you can use whatever number necessary to get the right frame. This gives you the whole Fully.Qualified.Namespace.Class.MethodName, which can be quite useful.
Tuesday, August 17, 2010
Dan Soltesz -blog | Silverlight datagrid double click behavior
Dan Soltesz -blog | Silverlight datagrid double click behavior
Totally worth a look. Will follow up with more info later.
Totally worth a look. Will follow up with more info later.
Friday, August 13, 2010
System.IO.DirectoryInfo extension method: Recursively print directory structure
Yeah, lots of extension method posts today. I'm just going through my projects and posting the good ones.
Actually, this is one I did when I was looking at editing a .xlsx doc without Excel installed. It turns out that .xlsx docs are actually zip files. When decompressed, it's got several levels of directories. I wanted to show someone the directory structure on a forum, but I didn't feel like typing it all out, so I typed (more) code to do it for me. Amazing how we'll waste effort writing a program for something that was probably faster to do without it.
I also used it as an excuse to learn about default parameters. C# now supports them. You could call this method by providing just one parameter, because all the others are provided automatically. Also note that you can use any TextWriter, not just Console.Out. You could make a StreamWriter and output it to text.
Anyway, that was off topic. Here's the code.
Here's a use case:
Expected output:
Actually, this is one I did when I was looking at editing a .xlsx doc without Excel installed. It turns out that .xlsx docs are actually zip files. When decompressed, it's got several levels of directories. I wanted to show someone the directory structure on a forum, but I didn't feel like typing it all out, so I typed (more) code to do it for me. Amazing how we'll waste effort writing a program for something that was probably faster to do without it.
I also used it as an excuse to learn about default parameters. C# now supports them. You could call this method by providing just one parameter, because all the others are provided automatically. Also note that you can use any TextWriter, not just Console.Out. You could make a StreamWriter and output it to text.
Anyway, that was off topic. Here's the code.
using System.IO;
namespace DirectoryExtensions
{
public static class DirectoryExtensions
{
public static void PrintDirectoryStructure(this DirectoryInfo directory, TextWriter writer, string prefix = ">", string spacer = "--")
{
writer.WriteLine(string.Format("{0}{1} (dir)", prefix, directory.Name));
prefix = spacer + prefix;
foreach (FileInfo file in directory.GetFiles())
writer.WriteLine(string.Format("{0}{1} (file)", prefix, file.Name));
DirectoryInfo[] subDirectories = directory.GetDirectories("*", SearchOption.TopDirectoryOnly);
if (subDirectories.Length > 0)
foreach (DirectoryInfo subDirectory in subDirectories)
PrintDirectoryStructure(subDirectory, writer, prefix, spacer);
}
}
}
Here's a use case:
DirectoryInfo directory = new DirectoryInfo(@"c:\dev\test"); directory.PrintDirectoryStructure(Console.Out);
Expected output:
>test (dir) -->subdir1 (dir) ---->textfile.txt (file) ---->subdirA (dir) ---->subdirB (dir) ------>asdf.txt (file) ------>some text file.txt (file) -->subdir2 (dir) ---->some text file.txt (file) -->subdir3 (dir)
Extension method to export a Silverlight Datagrid to CSV
Well, I couldn't figure out how to export it as an excel doc, but CSV is just as good...right? (Of course not, but it's good enough.)
This is an extension method, so you'd have to call it with dataGrid1.Export();
This is an extension method, so you'd have to call it with dataGrid1.Export();
public static class DataGridExtensions
{
public static void Export(this DataGrid dg)
{
SaveExportedGrid(ExportDataGrid(true, dg));
}
public static void Export(this DataGrid dg, bool withHeaders)
{
SaveExportedGrid(ExportDataGrid(withHeaders, dg));
}
private static void SaveExportedGrid(string data)
{
SaveFileDialog sfd = new SaveFileDialog() { DefaultExt = "csv", Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*", FilterIndex = 1 };
if (sfd.ShowDialog() ?? false)
{
using (StreamWriter sr = new StreamWriter(sfd.OpenFile()))
sr.Write(data);
}
}
private static string ExportDataGrid(bool withHeaders, DataGrid grid)
{
string colPath;
System.Reflection.PropertyInfo propInfo;
System.Windows.Data.Binding binding;
System.Text.StringBuilder strBuilder = new System.Text.StringBuilder();
System.Collections.IList source = (grid.ItemsSource as System.Collections.IList);
if (source == null)
return "";
List<string> headers = new List<string>();
grid.Columns.ToList().ForEach(col =>
{
if (col is DataGridBoundColumn)
{
headers.Add(FormatCSVField(col.Header.ToString()));
}
});
strBuilder
.Append(String.Join(",", headers.ToArray()))
.Append("\r\n");
foreach (Object data in source)
{
List<string> csvRow = new List<string>();
foreach (DataGridColumn col in grid.Columns)
{
if (col is DataGridBoundColumn)
{
binding = (col as DataGridBoundColumn).Binding;
colPath = binding.Path.Path;
propInfo = data.GetType().GetProperty(colPath);
if (propInfo != null)
{
csvRow.Add(FormatCSVField(propInfo.GetValue(data, null).ToString()));
}
}
}
strBuilder
.Append(String.Join(",", csvRow.ToArray()))
.Append("\r\n");
}
return strBuilder.ToString();
}
private static string FormatCSVField(string data)
{
return String.Format("\"{0}\"",
data.Replace("\"", "\"\"\"")
.Replace("\n", "")
.Replace("\r", "")
);
}
}
Convert Word and Excel to PDFs in C#
I had a very repetitive task I had to perform. Take a directory full of Word documents, open each, and do a Save As -> PDF on each of them. Not in this lifetime. So I wrote a quick program for it, and included Excel just to boot. I'll show the important methods.
You must have Office 2007 or greater installed on the machine the code will run on.
Add a reference to:
Microsoft Excel 12.0 Object Library (or greater)
Microsoft Word 12.0 Object Library (or greater)
Both can be found in the COM tab of the Add Reference dialog.
Here's the code:
You must have Office 2007 or greater installed on the machine the code will run on.
Add a reference to:
Microsoft Excel 12.0 Object Library (or greater)
Microsoft Word 12.0 Object Library (or greater)
Both can be found in the COM tab of the Add Reference dialog.
Here's the code:
using System;
using Word = Microsoft.Office.Interop.Word;
using Excel = Microsoft.Office.Interop.Excel;
...
void ExportExcel(string infile, string outfile)
{
Excel.Application excelApp = null;
try
{
excelApp = new Excel.Application();
excelApp.Workbooks.Open(infile);
excelApp.ActiveWorkbook.ExportAsFixedFormat(Excel.XlFixedFormatType.xlTypePDF, outfile);
}
finally
{
if (excelApp != null)
excelApp.Quit();
}
}
void ExportWord(string infile, string outfile)
{
Word.Application wordApp = null;
try
{
wordApp = new Word.Application();
wordApp.Documents.Open(infile);
wordApp.ActiveDocument.ExportAsFixedFormat(outfile, Word.WdExportFormat.wdExportFormatPDF);
}
finally
{
if (wordApp != null)
wordApp.Quit();
}
}
Subscribe to:
Posts (Atom)