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;
}

}
}


參考資料:


2012年1月26日 星期四

在啟動Expression Blend 4 時Crash

這是.Net 4.5 Developer Preview的相容性問題。這個問題已經被微軟修正了,但是修正的時間太晚了,所以沒有被放在下載的檔案中(preview build)。

修正方式為執行以下命令:

  • %windir%\Microsoft.NET\Framework\v4.0.30319\ngen uninstall "%ProgramFiles(x86)%\Microsoft Expression\Blend 4\Microsoft.Expression.Framework.dll"
  • %windir%\Microsoft.NET\Framework\v4.0.30319\ngen uninstall "%ProgramFiles(x86)%\Microsoft Expression\Blend 4\Microsoft.Expression.Blend.dll"
  • %windir%\Microsoft.NET\Framework\v4.0.30319\ngen uninstall "%ProgramFiles(x86)%\Microsoft Expression\Blend 4\Microsoft.Expression.Project.dll"
  • 如果有安裝Blend 4 SP1或後續的SPx,需要執行                                                                                                                                       %windir%\Microsoft.NET\Framework\v4.0.30319\ngen uninstall "%ProgramFiles(x86)%\Microsoft Expression\Blend 4\Microsoft.Expression.WindowsPhone.dll"

如果是使用x86系統的話,需要移除路徑中的"(x86)"。

參考資料: