2012年7月1日 星期日

[Rx]使用LinqPad 4來測試Reactive Extension

  1. 先到 LinqPad官網 下載 LinqPad。需要第4版以上才有支援Rx。
  2. 下載 Reactive Extensions (Rx) v2.0 Release Candidate
  3. 設定LinqPad的Query Properties:[Query]=>[Query Properties]或按F4來設定。設定需要依據Assembly的結構,如下圖:

               image

              image

             image

  4. 右邊可以使用C# Statement(s)來做運算。

             image

  5. 也可以選擇C# Program來運算。

                  image

參考資料:

2012年6月14日 星期四

使用Expression Encoder進行影片轉檔

測試的程式碼如下,這邊是轉出為WMV的VC-1格式,
如果要轉檔成MP4的格式,需要使用"Expression Encoder 4 Pro (with codecs)"授權版本,不然會出現錯誤訊息。
image
using System;
using Microsoft.Expression.Encoder;
using Microsoft.Expression.Encoder.Profiles;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MediaItem mediaItem = new MediaItem(@"C:\Temp\24.wmv");

//mediaItem.OutputFormat = new MP4OutputFormat();
WindowsMediaOutputFormat wmof = new WindowsMediaOutputFormat();
wmof.VideoProfile = new MainVC1VideoProfile();
wmof.AudioProfile = new WmaAudioProfile();
mediaItem.OutputFormat = wmof;

//Creates job and media item for the video to be encoded
Job job = new Job();
job.MediaItems.Add(mediaItem);

//Sets output directory
job.OutputDirectory = @"C:\Temp\converted";

//job.DefaultMediaOutputFileName = "24.mp4";
job.DefaultMediaOutputFileName = "24.wmv";

//Sets up progress callback function
job.EncodeProgress += new EventHandler<EncodeProgressEventArgs>(OnProgress);

//Encodes
Console.WriteLine("Encoding…");
job.Encode();
Console.WriteLine("\nFinished encoding.");
job.Dispose();

Console.ReadKey();
}

static void OnProgress(object sender, EncodeProgressEventArgs e)
{
Console.Write("\b\b\b\b\b\b\b");
Console.Write("{0:F2}%", e.Progress);
}

}
}
參考資料:


  • C:\Program Files (x86)\Microsoft Expression\Encoder 4\SDK

  • C:\Program Files (x86)\Microsoft Expression\Encoder 4\zh-Hant\Encoder.chm

2012年6月13日 星期三

關於C#裡 System.DBNull.Value & Convert.IsDBNull 的迷思

繼續自話題關於C#裡 System.DBNull.Value & Convert.IsDBNull 的迷思

原貼為:

想請教一下, 在C# 裡, 我要判斷資料表欄位是否為 Null 值, 是要用

if (DataTable.Rows[0][0] == System.DBNull.Value)

{

}

還是要用

if (Convert.IsDBNull(DataTable.Rows[0][0]))

{

}

那一個來做比較好? 為什麼?

正確的答案是:

Convert.IsDBNull 比較好。

為什麼?

DataTable.Rows[0][0] 傳回來的值,或說取自資料庫的值,傳回的型別大都是Object,必須要先利用轉型才可以正確判斷。

使用 if (DataTable.Rows[0][0] == System.DBNull.Value) 大都是False,微軟不會沒事找事做,微軟的東西也會經過一定的測試流程才發佈出來,

盡量使用可靠的東西準沒錯。

備註:

我遇到的錯誤情況是

if (tr["Tradition"] != DBNull.Value) btrTradition.ReportComplete = Convert.ToDateTime(tr["Tradition"]);
參考資料:

2012年6月5日 星期二

[WP7]Live Tile偵錯

在WMAppManifest.xml的原有<Tasks>加上程式碼,如下:

<Tasks>
  <
DefaultTask  Name ="_default" NavigationPage="View/LoginPage.xaml"/>
  <!--
For Live Tile Debug Start-->
  <
ExtendedTask Name="BackgroundTask">
    <
BackgroundServiceAgent Specifier="ScheduledTaskAgent" Name="ScheduledTaskAgent1"
                           
Source="DummyAgent" Type="DummyAgent.ScheduledAgent" />
  </
ExtendedTask>
  <!--
For Live Tile Debug End-->
</
Tasks>

在Release正式版之前,記得拿掉這個區段。

參考資料:

2012年5月26日 星期六

WebClient和HttpWebRequest的不同

WebClient 是 HttpWebRequest 類相關的包裝類,用於執行 Web 服務請求。WebClient 更易於使用,因為它會將結果數據返回到應用程序的 UI 線程,因此應用程序不需要將數據封送到 UI 線程。但是,如果應用程序處理 UI 線程上的 Web 服務數據,則 UI 將直到處理完成才做出響應,這樣就會導致很差的用戶體驗,尤其是要處理的數據集過大時。

使用 HttpWebRequest 代替 WebClient
使用 HttpWebRequest 發出 Web 服務請求。處理異步請求線程上的結果數據,然後使用 BeginInvoke 將數據封送到 UI 線程。

另外,HttpWebRequest可以針對環境和Cookie來做特定的設置,這是使用WebClient所沒有辦法做到的。

參考資源:

2012年5月13日 星期日

[SVN]將已簽入SVN的變更集重新打包為資料夾

可以很方便的對客製的同一工作項目進行覆蓋式的修改。

因為不是每一個客戶都有SVN的Patch可用,也不適合對不透明的系統使用SVN的Patch指令。

 

限制:

這裡只有做新增的部分,保留刪除與修改功能,有需要的人也可以依據自己的工作來最對應的修改。

需要安裝SVN客戶端 – TortoiseSVN

只適用於台灣地區,其他地區可能在顯示上會有亂碼,但不影響功能。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using System.Xml.Linq;
namespace SvnPkg
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 3)
            {
                Console.WriteLine("snvlog: 將指定的SVN變更集整理到指定的目錄下。");
                Console.WriteLine("用法:svnpkg [專案根目錄] [輸出目錄] [版本變更集]");
                Console.WriteLine(@"例如:svnlog D:\SVN\XXXXXX D:\Temp 228,230:231");
                return;
            }
            String SvnPath = @"C:\Program Files\TortoiseSVN\bin\svn.exe";
            String ProjectPathArg = args[0];
            String OutputPathArg = args[1];
            String ChangesetArg = args[2];
            if (!File.Exists(SvnPath))
            {
                Console.WriteLine("找不到svn:" + SvnPath);
            }
            //解析revision
            List<int> Changesets = new List<int>();
            foreach (String sub in ChangesetArg.Split(','))
            {
                if (sub.Contains(':'))
                {
                    int start = Convert.ToInt32(sub.Split(':')[0]);
                    int end = Convert.ToInt32(sub.Split(':')[1]);
                    for (int i = start; i <= end; i++)
                    {
                        if (!Changesets.Contains(i))
                        {
                            Changesets.Add(i);
                        }
                    }
                }
                else
                {
                    if (!Changesets.Contains(Convert.ToInt32(sub)))
                    {
                        Changesets.Add(Convert.ToInt32(sub));
                    }
                }
            }
            //依據變更集的先後順序排列
            Changesets.Sort();
            //Console.WriteLine(args[0]);
            Process svnProcess = new Process();
            svnProcess.StartInfo.FileName = SvnPath;
            svnProcess.StartInfo.CreateNoWindow = true;
            svnProcess.StartInfo.UseShellExecute = false;
            svnProcess.StartInfo.StandardErrorEncoding = Encoding.UTF8;
            svnProcess.StartInfo.StandardOutputEncoding = Encoding.UTF8;
            svnProcess.StartInfo.RedirectStandardError = true;
            svnProcess.StartInfo.RedirectStandardInput = true;
            svnProcess.StartInfo.RedirectStandardOutput = true;
            XDocument doc;
            foreach (int cs in Changesets)
            {
                svnProcess.StartInfo.Arguments = "log " + ProjectPathArg + " -v -r " + cs.ToString() + " --xml";
                svnProcess.Start();
                doc = XDocument.Load(svnProcess.StandardOutput);
                //String revision = doc.Document.Descendants("logentry").First().Attribute("revision").Value;
                //String msg = doc.Document.Descendants("msg").First().Value;
                //String date = doc.Document.Descendants("date").First().Value;
                //Console.WriteLine("revision:" + revision + " " + msg);                
                foreach (XElement elem in doc.Document.Descendants("path"))
                {
                    String basePath = elem.Value.Replace('/', '\\');
                    if (basePath.StartsWith("\\"))
                    {
                        basePath = basePath.Substring(1);
                    }
                    if (elem.Attribute("kind").Value == "file")
                    {
                        switch (elem.Attribute("action").Value)
                        {
                            case "A": //Add
                            case "M":  //Modify
                                String srcFile = Path.Combine(ProjectPathArg, basePath);
                                String descFile = Path.Combine(OutputPathArg, basePath);
                                String descDir = descFile.Substring(0, descFile.LastIndexOf('\\'));
                                
                                if (!Directory.Exists(descDir))
                                {
                                    Directory.CreateDirectory(descDir);
                                }
                                File.Copy(srcFile, descFile,true);
                                break;
                            default:
                                Console.WriteLine("未處理的動作:" + elem.Attribute("action").Value);
                                break;
                        }                        
                    }
                    else if (elem.Attribute("kind").Value == "dir")
                    {
                        ;
                    }
                    else
                    {
                        Console.WriteLine("未處理的種類:" + elem.Attribute("kind").Value);
                    }
                }
                //顯示目前處理的revision(使用big5才不會有亂碼)
                svnProcess.StartInfo.Arguments = "log " + ProjectPathArg + " -v -r " + cs.ToString();
                svnProcess.StartInfo.StandardOutputEncoding = Encoding.GetEncoding("big5");
                svnProcess.Start();
                Console.WriteLine(svnProcess.StandardOutput.ReadToEnd());
                //回覆解析XML需要使用的UTF8編碼
                svnProcess.StartInfo.StandardOutputEncoding = Encoding.UTF8;
            }
            Console.WriteLine("Done!");
        }
    }
}

2012年3月16日 星期五

[Rx]Reactive Observable方法的比較

網路上有一些範例,有些可以執行,有些連成員的方法都找不到,大部分都是因為使用了不同的Assembly,

所以下面列出這些不一樣的地方,我們就可以少走一些彎路啦。

  System.Reactive.Linq Microsoft.Phone.Reactive

簽名、種類都相同的

(黃底表示下面有類似的)

Aggregate
All(TSource)
Amb
And(TLeft, TRight)
Any
AsObservable(TSource)
Average
Cast(TResult)
Catch
CombineLatest(TLeft, TRight, TResult)
Concat
Contains
Count(TSource)
Defer(TValue)
Delay
Dematerialize(TSource)
DistinctUntilChanged
Do
Empty
Finally(TSource)
FromAsyncPattern
FromEvent
Generate
GetEnumerator(TSource)
GroupBy
Interval
Latest(TSource)
LongCount(TSource)
Materialize(TSource)
Max
MaxBy
Merge
Min
MinBy
MostRecent(TSource)
Never(TValue)
Next(TSource)
ObserveOn
OfType(TResult)
OnErrorResumeNext
Publish
Range
RefCount(TSource)
Repeat
Replay
Retry
Return
Sample
Scan
Select
SelectMany
Skip(TSource)
SkipLast(TSource)
SkipUntil(TSource, TOther)
Start
StartWith
Subscribe
SubscribeOn
Sum
Switch(TSource)
Synchronize
TakeLast(TSource)
TakeUntil(TSource, TOther)
Then(TSource, TResult)
Throttle
Throw
TimeInterval
Timeout
Timer
Timestamp
ToAsync
ToEnumerable(TSource)
ToObservable
Using(TSource, TResource)
Where
Zip

有部分不相同者

(黃底表示上面有類似的)

 

Buffer
Create
First
FirstOrDefault
Join(TLeft, TRight, TLeftDuration, TRightDuration, TResult)
Last
LastOrDefault
Single
SingleOrDefault
SkipWhile
Take(TSource)
TakeWhile
BufferWithCount
BufferWithTime
BufferWithTimeOrCount
Create(TSource)
CreateWithDisposable(TSource)
First(TSource)
FirstOrDefault(TSource)
Join
Last(TSource)
LastOrDefault(TSource)
Single(TSource)
SingleOrDefault(TSource)
SkipWhile(TSource)
Take
TakeWhile(TSource)
 

只有一邊有的


(黃底表示上面有類似的)

DefaultIfEmpty
Distinct
ElementAt(TSource)
ElementAtOrDefault(TSource)
ForEach(TSource)
FromEventPattern
GroupByUntil
GroupJoin(TLeft, TRight, TLeftDuration, TRightDuration, TResult)
IgnoreElements(TSource)
Multicast
PublishLast
SequenceEqual
ToArray(TSource)
ToDictionary
ToEvent
ToEventPattern(TEventArgs)
ToList(TSource)
ToLookup
When
Window
Case
DoWhile(TSource)
For(TSource, TResult)
ForkJoin
GenerateWithTime
If(TResult)
IsEmpty(TSource)
Let
ObserveOnDispatcher(TSource)
Prune
RemoveTimeInterval(TSource)
RemoveTimestamp(TSource)
Run
Scan0(TSource, TAccumulate)
SubscribeOnDispatcher(TSource)
While(TSource)

參考資料:

2012年3月14日 星期三

[Rx]無法將 Lambda 運算式 轉換為型別 'System.IObserver<string>',因為它不是委派型別

 

image

結果是:需要 using Microsoft.Phone.Reactive; 完全和轉型沒有關係,哈哈。

另一種情況是Lambda大括號裡面的敘述有錯誤造成的。

這是我看過最奇怪的一個錯誤訊息了。

2012年3月12日 星期一

[WP7]由檔案路徑讀取IsolatedStarage的圖檔

using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using Microsoft.Phone;
namespace XXXX.Common
{
    public class FilePathToImageConverter : IValueConverter
    {
        private static IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string path = value as string;
            if (String.IsNullOrEmpty(path))
                return null;
            if ((path.Length > 9) && (path.ToLower().Substring(0, 9).Equals("isostore:")))
            {
                using (IsolatedStorageFileStream isfs = isf.OpenFile(path.Substring(9), FileMode.Open, FileAccess.Read))
                {
                    WriteableBitmap wb = PictureDecoder.DecodeJpeg(isfs, 80, 50);
                    return wb;                    
                }
            }
            else
            {
                BitmapImage bi = new BitmapImage(new Uri(path, UriKind.Relative));
                return bi;
            }
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

可以這樣使用

<common:FilePathToImageConverter x:Key="FilePathToImageConverter" />
<Image x:Name="Image1" Source="{Binding ImageSource,Converter={StaticResource FilePathToImageConverter}}" Width="80" Height="50" ></Image>

2012年2月19日 星期日

WPF體系的邏輯樹/視覺樹常用操作

 

適用WPF,部分適用於Silverlight。

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;

namespace OrcaPlayer.Common
{
public class TreeHelper
{
private static object _SyncRoot = new object();

<summary>
IsolatedStorageHelper Static Constructor.
</
summary>
static TreeHelper()
{

}

private static TreeHelper _instance = null;
<summary>
</
summary>
public static TreeHelper Instance
{
get
{
lock (_SyncRoot)
{
if (_instance == null)
{
_instance = new TreeHelper();
}
return _instance;
}
}
}


public DependencyObject FindVirtualTreeRoot(DependencyObject initial)
{
DependencyObject current = initial;
DependencyObject result = initial;

while (current != null)
{
result = current;

if (current is Visual || current is Visual3D)
{
current = VisualTreeHelper.GetParent(current);
}
else
{
current = LogicalTreeHelper.GetParent(current);
}
}

return result;
}

public DependencyObject FindLogicalTreeRoot(DependencyObject initial)
{
DependencyObject current = initial;
DependencyObject result = initial;

while (current != null)
{
result = current;
current = LogicalTreeHelper.GetParent(current);
}

return result;
}

//using System.Windows;
public DependencyObject GetTemplateParent(DependencyObject depObj)
{
FrameworkElement fe = depObj as FrameworkElement;
FrameworkContentElement fce = depObj as FrameworkContentElement;

DependencyObject result;

if (fe != null)
{
result = fe.TemplatedParent;
}
else if (fce != null)
{
result = fce.TemplatedParent;
}
else
{
result = null;
}

return result;
}

//最近邏輯樹上的父節點
public DependencyObject FindClosestLogicalAncestor(DependencyObject initial)
{
DependencyObject current = initial;
DependencyObject result = initial;

while (current != null)
{
DependencyObject logicalParent = LogicalTreeHelper.GetParent(current);

if (logicalParent != null)
{
result = current;
break;
}

current = VisualTreeHelper.GetParent(current);
}

return result;
}

//最近視覺樹上的父節點
public DependencyObject FindClosestVisualAncestor(DependencyObject initial)
{
if (initial is Visual || initial is Visual3D)
{
return initial;
}

DependencyObject current = initial;
DependencyObject result = initial;

while (current != null)
{
result = current;

if (current is Visual || current is Visual3D)
{
result = current;
break;
}
else
{
current = LogicalTreeHelper.GetParent(current);
}
}

return result;
}

//顯示邏輯樹
//private TreeView tree = new TreeView();
public void PopulateLogicalTree(TreeViewItem parentItem, object currentElement)
{
TreeViewItem item = new TreeViewItem();

item.IsExpanded = true;

if (parentItem == null)
{
item.Header = currentElement.GetType().Name;
tree.Items.Add(item);
}
else
{
item.Header = currentElement.GetType().Name;
parentItem.Items.Add(item);
}

DependencyObject curObject = currentElement as DependencyObject;

if (curObject != null)
{
foreach (object chElement in LogicalTreeHelper.GetChildren(curObject))
{
PopulateLogicalTree(item, chElement);
}
}
}

//顯示視覺樹
//private TreeView tree = new TreeView();
public void PopulateVisualTree(TreeViewItem parentItem, DependencyObject currentElement)
{
TreeViewItem item = new TreeViewItem();

item.IsExpanded = true;

if (parentItem == null)
{
item.Header = currentElement.GetType().Name;
tree.Items.Add(item);
}
else
{
item.Header = currentElement.GetType().Name;
parentItem.Items.Add(item);
}

int visualChildrenCount = VisualTreeHelper.GetChildrenCount(currentElement);

for (int i = 0; i < visualChildrenCount; i++)
{
DependencyObject visualChild = VisualTreeHelper.GetChild(currentElement, i);
PopulateVisualTree(item, visualChild);
}
}

//ex: CheckBox chb = this.FindFirstVisualChild<CheckBox>(listViewItem)
public T FindFirstVisualChild<T>(DependencyObject parentElement) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parentElement); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parentElement, i);

if (child != null && child is T)
{
return child as T;
}
else
{
T result = FindFirstVisualChild<T>(child);

if (result != null)
{
return result;
}
}
}

return null;
}

//TextBlock textBlock = GetFrameworkElementByName<TextBlock>(rowPresenter, "textBlock");
public T GetFrameworkElementByName<T>(FrameworkElement parentElement, String name) where T : FrameworkElement
{
FrameworkElement child = null;

for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(parentElement); i++)
{
Debug.WriteLine("TreeHelper.cs::GetFrameworkElementByName " + parentElement.GetType().ToString() + " " + i.ToString());
child = VisualTreeHelper.GetChild(parentElement, i) as FrameworkElement;

if (child != null && child.Name == name && child.GetType() == typeof(T))
{
break;
}

else if (child != null)
{
child = GetFrameworkElementByName<T>(child, name);
}
}

return child as T;
}

//ContentPresenter cp = VisualTreeHelper.GetChild(CInfoContentControl, 0) as ContentPresenter;
//Button DownloadButton = TreeHelper.Instance.FindVisualChild<Button>(cp, 0, 3, 0, 0, 1) as Button;
//第二參數為第一參數下的的每一層子元素(子元素從0起算)
public T FindVisualChild<T>(DependencyObject parentElement, params int[] list) where T : DependencyObject
{
DependencyObject child = null;
for (int i = 0; i < list.Length; i++)
{
Debug.WriteLine("i=[" + i.ToString() + "] list[i]=[" + list[i].ToString() + "]");

if (i == 0)
{
if (VisualTreeHelper.GetChildrenCount(parentElement) > 0)
{
child = VisualTreeHelper.GetChild(parentElement, list[0]);
Debug.WriteLine("子元素型別=[" + child.GetType().ToString() + "]");
}
else
{
Debug.WriteLine(i.ToString() + " 子元素個數=[" + VisualTreeHelper.GetChildrenCount(parentElement).ToString() + "]");
}
}
else
{
if (VisualTreeHelper.GetChildrenCount(child) > 0)
{
child = VisualTreeHelper.GetChild(child, list[i]);
Debug.WriteLine("子元素型別=[" + child.GetType().ToString() + "]");
}
else
{
Debug.WriteLine(i.ToString() + " 子元素個數=[" + VisualTreeHelper.GetChildrenCount(child).ToString() + "]");
}
}
}

if (child != null && child is T)
{
return child as T;
}
else
{
return null;
}
}


public static T GetValue<T>(this BindingExpression expression, object dataItem)
{
if (expression == null || dataItem == null)
{
return default(T);
}

string bindingPath = expression.ParentBinding.Path.Path;
string[] properties = bindingPath.Split('.');

object currentObject = dataItem;
Type currentType = null;

for (int i = 0; i < properties.Length; i++)
{
currentType = currentObject.GetType();
PropertyInfo property = currentType.GetProperty(properties[i]);
if (property == null)
{
currentObject = null;
break;
}
currentObject = property.GetValue(currentObject, null);
if (currentObject == null)
{
break;
}
}

return (T)currentObject;
}

}
}


參考資料: