tag:blogger.com,1999:blog-41997506736507939272024-03-05T17:53:03.320-08:00小狙擊的悠閒日子JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-4199750673650793927.post-26658684666089305662021-07-04T01:52:00.005-07:002021-07-05T22:37:50.555-07:00Blazor.WebForm.UI - Blazor Component與WebForm Control
<p>StarRatingComponent.razor</p>
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>@for (int i = 1; i <= 5; i++)
{
int rating = i;
<a style="color: @GetColor(rating);font-size:30px;" href="javascript:" @onclick="() => OnChanged(rating)">★</a>
}
@code {
[Parameter]
public int CurrentRating { get; set; }
[Parameter]
public EventCallback<int> Changed { get; set; }
private void OnChanged(int rating)
{
this.CurrentRating = rating;
if (Changed.HasDelegate)
{
Changed.InvokeAsync(rating);
}
}
private string GetColor(int rating)
{
if (rating <= this.CurrentRating)
{
return "#f49813";
}
else
{
return "#cccccc";
}
}
}
</code></pre>
<p>StarRatingControl.cs</p>
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code> public class StarRatingControl : UserControl
{
public int CurrentRating { get; set; }
public event EventHandler Changed;
protected override void OnInit(EventArgs e)
{
for (int i = 1; i <= 5; i++)
{
LinkButton linkButton = new LinkButton();
linkButton.Style[HtmlTextWriterStyle.FontSize] = "30px";
linkButton.Text = "★";
linkButton.CommandArgument = i.ToString();
linkButton.Click += this.LinkButton_Click;
linkButton.PreRender += this.LinkButton_PreRender;
this.Controls.Add(linkButton);
}
base.OnInit(e);
}
private void LinkButton_Click(object sender, EventArgs e)
{
LinkButton linkButton = (LinkButton)sender;
int rating = Convert.ToInt32(linkButton.CommandArgument);
this.CurrentRating = rating;
if (Changed != null)
{
Changed.Invoke(this, e);
}
}
private void LinkButton_PreRender(object sender, EventArgs e)
{
LinkButton linkButton = (LinkButton)sender;
int rating = Convert.ToInt32(linkButton.CommandArgument);
if (rating <= this.CurrentRating)
{
linkButton.Style[HtmlTextWriterStyle.Color] = "#f49813";
}
else
{
linkButton.Style[HtmlTextWriterStyle.Color] = "#cccccc";
}
}
}
</code></pre>
<p>StarRatingControlInComponent.razor</p>
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>@using System.Web.UI;
@inherits ControlComponent<StarRatingControl>
@this.RenderControl()
@code {
[Parameter]
public int CurrentRating
{
get
{
return this.Control.CurrentRating;
}
set
{
this.Control.CurrentRating = value;
}
}
[Parameter]
public EventCallback<int> Changed { get; set; }
protected override void OnInitialized()
{
this.Control.Changed += this.OnChanged;
}
private void OnChanged(object sender, EventArgs e)
{
if (Changed.HasDelegate)
{
Changed.InvokeAsync(this.CurrentRating);
}
}
}
</code></pre>
<p>StarRatingComponentInControl.cs</p>
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code> public class StarRatingComponentInControl : UserControl, IRenderComponentControl
{
private StarRatingComponent _starRating;
public int CurrentRating { get; set; }
public event EventHandler Changed;
private void OnChanged()
{
this.CurrentRating = _starRating.CurrentRating;
if (Changed != null)
{
Changed.Invoke(this, EventArgs.Empty);
}
}
Type IRenderComponentControl.ComponentType
{
get
{
return typeof(StarRatingComponent);
}
}
void IRenderComponentControl.ComponentReferenceCapture(object componentReference)
{
_starRating = (StarRatingComponent)componentReference;
}
void IRenderComponentControl.RenderAttributes(IHtmlAttributesWriter writer)
{
writer.AddSingleAttribute(nameof(this.CurrentRating), this.CurrentRating);
writer.AddEventAttribute<int>(nameof(this.Changed), this, this.OnChanged);
}
void IRenderComponentControl.RenderContents(IHtmlContentsWriter writer)
{
}
}
</code></pre>
<p>StarRatingList.razor</p>
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>@using System.Web.UI;
@page "/starrating-list"
@inherits ControlComponent
<h3>StarRating List</h3>
@for (int i = 1; i <= 5; i++)
{
@i
<StarRatingControlInComponent CurrentRating="i"></StarRatingControlInComponent>
<br />
}
<hr />
@this.RenderControl()
@code {
protected override void OnInitialized()
{
for (int i = 1; i <= 5; i++)
{
this.Controls.Add(new LiteralControl($"{i}"));
StarRatingComponentInControl starRating = new StarRatingComponentInControl();
starRating.CurrentRating = i;
this.Controls.Add(starRating);
this.Controls.Add(new LiteralControl("<br />"));
}
}
}
</code></pre>
JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-80239349513161474732020-12-12T23:16:00.005-08:002020-12-12T23:17:38.752-08:00[Applied]LINQ版本的視窗函數(SQL Window Function)<p>資料庫SQL中有一些配合Over字句Patition By群組後去處理集合<br />相當好用的視窗函數,例如編號用的Row_Number、Rank、Dense_Rank等等<br />似乎可以在LINQ中實現<br /><br />因此在新版本的Applied套件中新增了此項功能<br /><br />Nuget網址: <a href="https://www.nuget.org/packages/Applied/">https://www.nuget.org/packages/Applied/</a><br /><br /></p><p>底下為示範的程式</p>
<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-cs">public class TestData
{
public int Year { get; set; }
public string Name { get; set; }
public decimal Value { get; set; }
public decimal Sum { get; set; }
public decimal Average { get; set; }
public int RowNumber { get; set; }
public int Ntile { get; set; }
public int DenseRank { get; set; }
public int Rank { get; set; }
public decimal FirstValue { get; set; }
public decimal LastValue { get; set; }
public decimal NthValue { get; set; }
public decimal Lead { get; set; }
public decimal Lag { get; set; }
public decimal CumeDist { get; set; }
public decimal PercentRank { get; set; }
public decimal PercentileDisc { get; set; }
public decimal PercentileCont { get; set; }
public decimal KeepDenseRankFirst { get; set; }
public decimal KeepDenseRankLast { get; set; }
public decimal TeaTime { get; set; }
}</code></pre>
<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-cs">List<TestData> data = new List<TestData>();
data.Add(new TestData() { Year = 2019, Name = "A", Value = 111.1m });
data.Add(new TestData() { Year = 2019, Name = "B", Value = 333.3m });
data.Add(new TestData() { Year = 2019, Name = "C", Value = 333.3m });
data.Add(new TestData() { Year = 2019, Name = "A", Value = 222.2m });
data.Add(new TestData() { Year = 2019, Name = "C", Value = 444.4m });
data.Add(new TestData() { Year = 2019, Name = "A", Value = 222.2m });
data.Add(new TestData() { Year = 2019, Name = "B", Value = 333.3m });
data.Add(new TestData() { Year = 2019, Name = "C", Value = 555.5m });
data.Add(new TestData() { Year = 2020, Name = "A", Value = 111.1m });
data.Add(new TestData() { Year = 2020, Name = "B", Value = 333.3m });
data.Add(new TestData() { Year = 2020, Name = "A", Value = 222.2m });
data.Add(new TestData() { Year = 2020, Name = "C", Value = 333.3m });
data = data.GroupBy(a => new { a.Year }).AsPartition(p => p.OrderBy(a => a.Value).ThenBy(a => a.Name))
.Over(p => p.Sum(a => a.Value), (a, value) => a.Apply(() => new { Sum = value }))
.Over(p => p.Average(a => a.Value), (a, value) => a.Apply(() => new { Average = value }))
.Over(p => p.RowNumber(), (a, value) => a.Apply(() => new { RowNumber = value }))
.Over(p => p.Ntile(2), (a, value) => a.Apply(() => new { Ntile = value }))
.Over(p => p.DenseRank(), (a, value) => a.Apply(() => new { DenseRank = value }))
.Over(p => p.Rank(), (a, value) => a.Apply(() => new { Rank = value }))
.Over(p => p.FirstValue(a => a.Value), (a, value) => a.Apply(() => new { FirstValue = value }))
.Over(p => p.LastValue(a => a.Value), (a, value) => a.Apply(() => new { LastValue = value }))
.Over(p => p.NthValue(a => a.Value, 2), (a, value) => a.Apply(() => new { NthValue = value }))
.Over(p => p.Lead(a => a.Value), (a, value) => a.Apply(() => new { Lead = value }))
.Over(p => p.Lag(a => a.Value), (a, value) => a.Apply(() => new { Lag = value }))
.Over(p => p.CumeDist(), (a, value) => a.Apply(() => new { CumeDist = value }))
.Over(p => p.PercentRank(), (a, value) => a.Apply(() => new { PercentRank = value }))
.Over(p => p.PercentileDisc(0.5m, a => a.Value), (a, value) => a.Apply(() => new { PercentileDisc = value }))
.Over(p => p.PercentileCont(0.5m, a => a.Value), (a, value) => a.Apply(() => new { PercentileCont = value }))
.Over(p => p.KeepDenseRankFirst(g => g.Sum(a => a.Value)), (a, value) => a.Apply(() => new { KeepDenseRankFirst = value }))
.Over(p => p.KeepDenseRankLast(g => g.Sum(a => a.Value)), (a, value) => a.Apply(() => new { KeepDenseRankLast = value }))
.ToList();</code></pre>
<p>執行結果</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPLjuM3x1k3mlmtg091wyjNP_9HPjsbBCzgf9E_K7UK35B795AFNP0Eq_N6g3MCV2en-BUw2tFsmyIB98XXtvqdc_kzg_J1W22O-W92L2c07BRFzo833lhZKVhSPgJKIs99SIn968-aFvJ/s1882/2020-12-13_105429.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="425" data-original-width="1882" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPLjuM3x1k3mlmtg091wyjNP_9HPjsbBCzgf9E_K7UK35B795AFNP0Eq_N6g3MCV2en-BUw2tFsmyIB98XXtvqdc_kzg_J1W22O-W92L2c07BRFzo833lhZKVhSPgJKIs99SIn968-aFvJ/w640-h145/2020-12-13_105429.png" width="640" /></a></div><br /> <p></p><p>其中Over方法的第一個Func參數有兩種型態</p>
<p>一個是直接由IEnumerable<TSource>集合回傳單一值IElement的彙總方法<br />
可以使用Linq原有的Sum、Average等等去計算集合部分的結果</p>
<p>另一個是IWindowFunctionFactory<TSource><br />
要回傳IWindowFunction<TSourceBase, IElement>的視窗函數物件,由該物件執行計算</p>
<p>目前已實現有15種一般的Window Function<br />
不過也許可能有特殊需求情況,需要自行去實現自訂的Window Function<br />
可以用IWindowFunction<TSourceBase, IElement>介面去達到自訂功能,如下</p><p>
</p>
<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-cs">public class TeaTime<TSourceBase, IElement> : IWindowFunction<TSourceBase, IElement>
{
private readonly Func<TSourceBase, IElement> _field;
public TeaTime(Func<TSourceBase, IElement> field)
{
if (field == null)
{
throw new ArgumentNullException("field");
}
_field = field;
}
public IEnumerable<TResult> GetPartitionResults<TSource, TResult>(IRankEnumerable<TSource> elements
, Func<TSource, IElement, TResult> selector) where TSource : TSourceBase
{
foreach (TSource element in elements)
{
IElement value = _field(element);
yield return selector(element, value);
}
}
}
public static class MyWindowFunctions
{
public static IWindowFunction<TSource, IElement> TeaTime<TSource, IElement>(this IWindowFunctionFactory<TSource> factory
, Func<TSource, IElement> field)
{
return new TeaTime<TSource, IElement>(field);
}
}</code></pre>
<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-cs">data = data.GroupBy(a => new { a.Year }).AsPartition(p => p.OrderBy(a => a.Value).ThenBy(a => a.Name))
.Over(p => p.TeaTime(a => a.Value), (a, value) => a.Apply(() => new { TeaTime = value }))
.ToList();</code></pre><p> </p>JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-76284705359293510532017-05-31T07:43:00.000-07:002017-05-31T07:46:41.203-07:00[Applied]簡易的資料對映轉換套件<br />
<br />
Applied是一個用於處理DTO屬性值對映複製的.NET元件<br />
<br />
概念來自於T-SQL的CROSS APPLY,所以擴充函式才會使用Lambda型態的參數做設計<br />
<br />
<br />
Nuget網址: <a href="https://www.nuget.org/packages/Applied/">https://www.nuget.org/packages/Applied/</a><br />
<br />
<br />
使用上非常簡單,首先宣告示範程式用的資料物件類別<br />
<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-cs hljs" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-radius: 0px; border: none; display: block; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 1em; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px; text-size-adjust: none;"> <span class="hljs-keyword" style="color: blue;">public</span> <span class="hljs-keyword" style="color: blue;">enum</span> UserEnum
{
None,
User
}
[Serializable]
<span class="hljs-keyword" style="color: blue;">public</span> <span class="hljs-keyword" style="color: blue;">class</span> <span class="hljs-title" style="color: #a31515;">User</span>
{
<span class="hljs-keyword" style="color: blue;">public</span> <span class="hljs-keyword" style="color: blue;">int</span> UserID { <span class="hljs-keyword" style="color: blue;">get</span>; <span class="hljs-keyword" style="color: blue;">set</span>; }
<span class="hljs-keyword" style="color: blue;">public</span> <span class="hljs-keyword" style="color: blue;">string</span> Name { <span class="hljs-keyword" style="color: blue;">get</span>; <span class="hljs-keyword" style="color: blue;">set</span>; }
<span class="hljs-keyword" style="color: blue;">public</span> DateTime? Time { <span class="hljs-keyword" style="color: blue;">get</span>; <span class="hljs-keyword" style="color: blue;">set</span>; }
<span class="hljs-keyword" style="color: blue;">public</span> UserEnum Enum { <span class="hljs-keyword" style="color: blue;">get</span>; <span class="hljs-keyword" style="color: blue;">set</span>; }
}
[Serializable]
<span class="hljs-keyword" style="color: blue;">public</span> <span class="hljs-keyword" style="color: blue;">class</span> <span class="hljs-title" style="color: #a31515;">UserViewModel</span>
{
<span class="hljs-keyword" style="color: blue;">public</span> <span class="hljs-keyword" style="color: blue;">int</span> UserID { <span class="hljs-keyword" style="color: blue;">get</span>; <span class="hljs-keyword" style="color: blue;">set</span>; }
<span class="hljs-keyword" style="color: blue;">public</span> <span class="hljs-keyword" style="color: blue;">string</span> Name { <span class="hljs-keyword" style="color: blue;">get</span>; <span class="hljs-keyword" style="color: blue;">set</span>; }
<span class="hljs-keyword" style="color: blue;">public</span> DateTime? Time { <span class="hljs-keyword" style="color: blue;">get</span>; <span class="hljs-keyword" style="color: blue;">set</span>; }
<span class="hljs-keyword" style="color: blue;">public</span> UserEnum Enum { <span class="hljs-keyword" style="color: blue;">get</span>; <span class="hljs-keyword" style="color: blue;">set</span>; }
}</code></pre>
然後建立一個陣列並對其使用Applied提供的擴充函式<br />
<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-cs hljs" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-radius: 0px; border: none; display: block; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 1em; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px; text-size-adjust: none;"> User[] users = <span class="hljs-keyword" style="color: blue;">new</span> User[]
{
<span class="hljs-keyword" style="color: blue;">new</span> User() { UserID = <span class="hljs-number">1</span>, Name = <span class="hljs-string" style="color: #a31515;">"Sam "</span> },
<span class="hljs-keyword" style="color: blue;">new</span> User() { UserID = <span class="hljs-number">2</span>, Name = <span class="hljs-string" style="color: #a31515;">"John "</span> }
};
users.Apply(a => <span class="hljs-keyword" style="color: blue;">new</span> { Time = DateTime.Now, Enum = UserEnum.User });
users.Trim();</code></pre>
<br />
這裡Apply()會令陣列的所有項目屬性與參數中給的賦值物件的屬性值設為一樣<br />
<br />
只要兩者的屬性名稱相同,型別相同或型別能相互轉換的<br />
<br />
Trim()則會除去所有字串屬性值的前後空白<br />
<br />
因為函式其實有回傳自身所以也能夠使用類似裝飾者的寫法或者用於Linq查詢語法內<br />
<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-cs hljs" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-radius: 0px; border: none; display: block; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 1em; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px; text-size-adjust: none;"> users.Apply(a => <span class="hljs-keyword" style="color: blue;">new</span> { Time = DateTime.Now, Enum = UserEnum.User }).Trim();</code></pre>
對於一般方式來說此行的程式則大約需要寫成這樣<br />
<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-cs hljs" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-radius: 0px; border: none; display: block; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 1em; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px; text-size-adjust: none;"> <span class="hljs-keyword" style="color: blue;">for</span> (<span class="hljs-keyword" style="color: blue;">int</span> i = <span class="hljs-number">0</span>; i < users.Length; i++)
{
users[i].Time = DateTime.Now;
users[i].Enum = UserEnum.User;
<span class="hljs-keyword" style="color: blue;">if</span> (users[i].Name != <span class="hljs-keyword" style="color: blue;">null</span>)
{
users[i].Name = users[i].Name.Trim();
}
}</code></pre>
如果每個物件需要設定的屬性越多型別轉換越多寫起來就會越麻煩複雜<br />
<br /><br />而且除了有設定好資料類別的資料物件可以使用這些函式以外<br /><br />DataTable,DataRow,IDictionary(Key為string)等型態的物件也可以使用這些函式設定或作為賦值的參數<br /><br />另外還有幾個相互轉換用的函式<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-cs hljs" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-radius: 0px; border: none; display: block; font-family: "Source Code Pro", Consolas, Courier, monospace; font-size: 1em; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px; text-size-adjust: none;"> UserViewModel[] vm1 = users.ToDataEnumerable<User, UserViewModel>().ToArray();
DataTable dt1 = users.ToDataTable();
Dictionary<<span class="hljs-keyword" style="color: blue;">string</span>, <span class="hljs-keyword" style="color: blue;">object</span>>[] ds1 = users.ToDictionaries().ToArray();
UserViewModel[] vm2 = dt1.ToDataEnumerable<UserViewModel>().ToArray();
UserViewModel[] vm3 = ds1.ToDataEnumerable<UserViewModel>().ToArray();
DataTable dt2 = vm1.ToDataTable();
DataTable dt3 = ds1.ToDataTable();
Dictionary<<span class="hljs-keyword" style="color: blue;">string</span>, <span class="hljs-keyword" style="color: blue;">object</span>>[] ds2 = vm1.ToDictionaries().ToArray();
Dictionary<<span class="hljs-keyword" style="color: blue;">string</span>, <span class="hljs-keyword" style="color: blue;">object</span>>[] ds3 = dt1.ToDictionaries().ToArray();</code></pre>
<br />
<br />
資料類別陣列,DataTable,Dictionary陣列皆可互相轉換<br />
<br />
<br />
然後是有關效能的部分<br />
<br />
<strike>Applied的對映功能主要是以TypeDescriptor的方式來達成<br />沒有需要程式先預初始化的設計,所以是每次呼叫都會自動的做一次Mapping動作<br />不過其中還是具有依靠陣列長度來判斷是否轉換為使用Expression Tree以加速處理的機制<br />(Expression Tree初始較慢執行較快,效益臨界值是訂672,以Array或List使用才能判斷)<br />固每次任務皆少筆數的話整體效能大致上應該不高,不過差別大概也感覺不到(筆數少)<br />就看請求任務的總次數多或不多來評估適不適合使用了</strike><br />
<br />
<br />
新版改以Expression Tree為主,在沒有需要程式先預初始化的設計情況<br />
<br />
第一次自動Mapping後存取屬性的Lambda會存入記憶體的字典中下次呼叫就能以類別來快取<br />
<div style="line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
https://dotblogs.com.tw/initials/2016/08/20/231753<br />
<br />
與這篇文章相同的百萬筆測試,<strike>結果為700~800左右,原生的14~17倍</strike><br />
<br />
結果為400~500,原生的10倍左右<br />
<br />
<br />
以上請參考,若有錯誤煩請告知,感謝~</div>
JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-7473742771078658062016-03-12T22:39:00.000-08:002016-03-12T22:58:12.799-08:00ASP.NET MVVM - 主從式網站資料的Cache服務<div class="article__desc" style="color: #555555; line-height: 22px; margin: 22px 0px;">
<div style="margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">主從式網站資料的Cache服務</span></div>
</div>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;"><a href="https://visualstudiogallery.msdn.microsoft.com/e63e6b76-6e15-470b-8bbe-2c3185b05635" style="color: #187a00; overflow-wrap: break-word; text-decoration: none; transition: all 0.1s ease-in-out; word-wrap: break-word;">Excalibur</a>中一直有個能夠利用Cache物件儲存網頁ViewState於後端伺服器中的功能</span><br />
<span style="background-color: white; font-size: x-small;">過去啟用需以Web.config設定Path的方式,但現在的新版本我們有了更快速方便使用的方法</span><br />
<span style="background-color: white; font-size: x-small;">只要直接在Page上加一行程式碼</span></div>
<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-cs hljs" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-radius: 0px; border: none; display: block; font-family: 'Source Code Pro', Consolas, Courier, monospace; font-size: 1em; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px;">[PageCacheViewState(<span class="hljs-keyword" style="color: blue;">true</span>, <span class="hljs-keyword" style="color: blue;">false</span>)]
<span class="hljs-keyword" style="color: blue;">public</span> <span class="hljs-keyword" style="color: blue;">partial</span> <span class="hljs-keyword" style="color: blue;">class</span> _<span class="hljs-title" style="color: #a31515;">Default</span> : <span class="hljs-title" style="color: #a31515;">System</span>.<span class="hljs-title" style="color: #a31515;">Web</span>.<span class="hljs-title" style="color: #a31515;">UI</span>.<span class="hljs-title" style="color: #a31515;">Page</span>
{
<span class="hljs-function"><span class="hljs-keyword" style="color: blue;">protected</span> <span class="hljs-keyword" style="color: blue;">void</span> <span class="hljs-title" style="color: #a31515;">Page_Load</span>(<span class="hljs-params"><span class="hljs-keyword" style="color: blue;">object</span> sender, EventArgs e</span>)
</span>{
}
}</code></pre>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">當PageCacheViewState使用後網頁前端原始碼</span></div>
<div style="background-color: whitesmoke; color: #555555; font-family: 'Helvetica Neue', Helvetica, Arial, 'Heiti TC', 'Apple LiGothic Medium', 微軟正黑體, sans-serif; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<a data-lightboximg="" href="https://az787680.vo.msecnd.net/user/jurio/1adc3126-78d5-4343-ab85-04f8ffcfb619/1457848247_3714.png" style="background-color: transparent; color: #187a00; overflow-wrap: break-word; text-decoration: none; transition: all 0.1s ease-in-out; word-break: break-word; word-wrap: break-word;"><img height="301" src="https://az787680.vo.msecnd.net/user/jurio/1adc3126-78d5-4343-ab85-04f8ffcfb619/1457848247_3714.png" style="background: rgb(255, 255, 255); border: 1px solid rgb(238, 238, 238); box-sizing: border-box; display: block; height: auto !important; max-width: 100%; padding: 5px;" width="810" /></a></div>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">產生到前端的網頁只有一段GUID資料,此功能Cache Timeout預設留存40分鐘(可web.config設定)</span></div>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">讓ASPX網頁的ViewState資料不要往返前後端在PostBack時消耗頻寬傳送,可大幅提升網頁效能速度</span></div>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">並且在新版本Excalibur使用Cache的方式也有項很特別的變更,就是其中附加了一隻新的Cache服務程式</span><br />
<span style="background-color: white; font-size: x-small;">只要當第一次Cache時類別庫會自動的在伺服器啟動一個Excalibur.Scabbard背景行程</span></div>
<div style="background-color: whitesmoke; color: #555555; font-family: 'Helvetica Neue', Helvetica, Arial, 'Heiti TC', 'Apple LiGothic Medium', 微軟正黑體, sans-serif; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<img height="472" src="https://az787680.vo.msecnd.net/user/jurio/1adc3126-78d5-4343-ab85-04f8ffcfb619/1457848390_75106.png" style="background: rgb(255, 255, 255); border: 1px solid rgb(238, 238, 238); box-sizing: border-box; display: block; height: auto !important; max-width: 100%; padding: 5px;" width="432" /></div>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">此行程的功用就是專門用來儲存Cache的,它會以TCP/IP的方式和持續和網站連線,將序列化後的資料儲存於其中</span></div>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">為何我們需要特地為Cache這麼做呢?因為IIS的機制本身會定期回收網站行程,而且IIS網站可以設定多行程並行</span><br />
<span style="background-color: white; font-size: x-small;">原本ASP.NET提供的Cache卻只能依附在單一網站行程內,只要工作區關閉重啟Cache資料必定會消失</span><br />
<span style="background-color: white; font-size: x-small;">若是設定多行程的網站,行程之間使用的Cache也不會是同一份資料</span><br />
<span style="background-color: white; font-size: x-small;">更有可能因為線上網站是有使用負載平衡,多台主機的資料根本沒辦法跨主機行程共用</span></div>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">預設的情況我們不需任何設定就會為一個網站開啟一個Excalibur.Scabbard行程</span><br />
<span style="background-color: white; font-size: x-small;">若需要跨網站或主機間使用,只要於Web.config中指定IP和Port即可</span></div>
<pre style="background-color: #eeeeee; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', Consolas, Courier, monospace; font-size: 15px; line-height: 22px; margin-bottom: 22px; margin-top: 22px; max-width: 100%; overflow: auto; padding: 4.5px 11px;"><code class="language-xml hljs" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-radius: 0px; border: none; display: block; font-family: 'Source Code Pro', Consolas, Courier, monospace; font-size: 1em; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px;"><span class="hljs-tag"><<span class="hljs-title" style="color: #a31515;">configuration</span>></span>
<span class="hljs-tag"><<span class="hljs-title" style="color: #a31515;">configSections</span>></span>
<span class="hljs-tag"><<span class="hljs-title" style="color: #a31515;">section</span> <span class="hljs-attribute">name</span>=<span class="hljs-value" style="color: #a31515;">"extensions"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value" style="color: #a31515;">"CachePage.ExtensionsConfigSection"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title" style="color: #a31515;">configSections</span>></span>
<span class="hljs-tag"><<span class="hljs-title" style="color: #a31515;">extensions</span>></span>
<span class="hljs-tag"><<span class="hljs-title" style="color: #a31515;">cacheService</span>></span>
<span class="hljs-tag"><<span class="hljs-title" style="color: #a31515;">netServer</span> <span class="hljs-attribute">hostName</span>=<span class="hljs-value" style="color: #a31515;">"127.0.0.1"</span> <span class="hljs-attribute">port</span>=<span class="hljs-value" style="color: #a31515;">"6143"</span>></span><span class="hljs-tag"></<span class="hljs-title" style="color: #a31515;">netServer</span>></span>
<span class="hljs-comment" style="color: green;"><!--<netClient hostName="127.0.0.1" port="6143"></netClient>--></span>
<span class="hljs-tag"></<span class="hljs-title" style="color: #a31515;">cacheService</span>></span>
<span class="hljs-tag"></<span class="hljs-title" style="color: #a31515;">extensions</span>></span>
<span class="hljs-tag"></<span class="hljs-title" style="color: #a31515;">configuration</span>></span></code></pre>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">很簡單的在主網站的Server用netServer設定,其他網站Client用netClient設定</span></div>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">然後這個Cache服務不僅僅只能用來暫存ViewState,Excalibur也提供了可以呼叫的方法</span><br />
<div style="background-color: whitesmoke; font-size: 15px;">
<br /></div>
<div style="background-color: whitesmoke; font-size: 15px;">
<img height="281" src="https://az787680.vo.msecnd.net/user/jurio/1adc3126-78d5-4343-ab85-04f8ffcfb619/1457848467_65178.png" style="background: rgb(255, 255, 255); border: 1px solid rgb(238, 238, 238); box-sizing: border-box; display: block; height: auto !important; max-width: 100%; padding: 5px;" width="613" /></div>
</div>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">只要將原始的Cache物件使用方式改成有Item的擴充函式就可以了</span></div>
<div style="color: #555555; line-height: 22px; margin-bottom: 22px; margin-top: 22px;">
<span style="background-color: white; font-size: x-small;">ps. Excalibur.Scabbard行程關閉條件是在IIS關閉網站後,沒有任何網站與它連線的5分鐘左右自動關閉</span></div>
<br />JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-41658133252462760932013-10-06T08:33:00.000-07:002013-10-12T14:14:09.640-07:00ASP.NET MVVM - 兩個Extensions UserControl互動與相互傳值的方法如果常在WebForm應用程式中切割一堆UserControl使用<br />
難免會碰上互動傳值的問題,而且解法應該不少<br />
普通情況只要頁面上有Register過ascx路徑都可以取得類別型態與Property/Event<br />
然後也能利用FindControl和Interface來處理...等等<br />
但若是兩個UserControl放置在千里之遙<br />
甚至不在氣泡事件OnBubbleEvent能解決的樣版關係的情況下<br />
可以試試以下設計的方法<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRLZGVvN89-Fs6qFXR5FavfrgFfXWGjokAVjih4JGFyDsBShMh9rvzGz8AvIlLH5yjBvo1S1YulJLU68NU545SzO9nqMA0NmxdtPnE7kj-EpTdhcvtUiPd0PbW35xRNteSHoByJspD1UVM/s1600/1.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRLZGVvN89-Fs6qFXR5FavfrgFfXWGjokAVjih4JGFyDsBShMh9rvzGz8AvIlLH5yjBvo1S1YulJLU68NU545SzO9nqMA0NmxdtPnE7kj-EpTdhcvtUiPd0PbW35xRNteSHoByJspD1UVM/s1600/1.PNG" /></a></div>
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpKuuuTSMQ0G4JZ_5_Q5g3lqZ570u53KJ7t14XQTWA6RHoSuKhuBEjwfFXXP-o-GCpPNYUJ2S86L3b0EwN9IJH6XE3-rbVdLT0EYtlAK_eKRe7htPvMT0mIKsJtXBEA5L4nf-PkVu8HHna/s1600/2.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpKuuuTSMQ0G4JZ_5_Q5g3lqZ570u53KJ7t14XQTWA6RHoSuKhuBEjwfFXXP-o-GCpPNYUJ2S86L3b0EwN9IJH6XE3-rbVdLT0EYtlAK_eKRe7htPvMT0mIKsJtXBEA5L4nf-PkVu8HHna/s1600/2.PNG" /></a></div>
<br />
SendMessage方法傳送的第一個參數即MessageNotify事件EventArgs的CommandName<br />
第二個參數即事件EventArgs的CommandArgument<br />
MessageNotify中的sender則是發送訊息的UserControl物件<br />
<br />
這裡呼叫SendMessage會對Page內所有Extensions UserControl註冊的MessageNotify事件進行觸發<br />
但是不會觸發發送訊息的UserControl自己本身註冊的MessageNotify事件<br />
所以也能在MessageNotify事件時呼叫SendMessage傳送其他訊息出去<br />
<br />
(MVVM 1.1.1.8版本以上加入)<br />
<br />
後記:在更新版本中加入了Attribute的使用方法,示例中的UserControl2可改寫成這樣<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxb5fb0NKTRTzKW97dm_CHsMVW7SMfuTpmwKhaH9fj-cgC-Zdo2ceHEbpKBDPBZdvDScEAcwGX4it8rVhxp0lx168tV9QcufCE3g7FSrXHVF-JJXwFTTEHNvY1UPlKOyYyeSaFRv-8x2WG/s1600/4.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxb5fb0NKTRTzKW97dm_CHsMVW7SMfuTpmwKhaH9fj-cgC-Zdo2ceHEbpKBDPBZdvDScEAcwGX4it8rVhxp0lx168tV9QcufCE3g7FSrXHVF-JJXwFTTEHNvY1UPlKOyYyeSaFRv-8x2WG/s1600/4.PNG" /></a></div>
<br />
相當於直接標註方法為可讓其他控制項以SendMessage公開呼叫的意思<br />
呼叫的Command為指定的方法名稱,Argument為參數JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-85223269034210729932013-09-25T14:41:00.002-07:002013-09-25T17:24:06.803-07:00ASP.NET MVVM - ExtensionsControl (2)這次MVVM更新到1.1.1.5版了,那這裡要介紹的新控制項是RouteManager跟HolderSource<br />
顧名思義第一個控制項八成是用來搞Url的Route用的<br />
第二個也一定和PlaceHolder用來動態載入控制項的功能有關<br />
<br />
首先要使用RouteManager因為要用到ASP.NET 4.0才加入的Route功能,需要在Global.asax中設定<br />
假設網站首頁的路徑是"~/Default.aspx"那麼Application_Start中就加入以下程式<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihFjP3UnJ4iTX73FrLfhQofZzb_4VQxzCd34hunGSmFoVSYkw78xuxnDuknrnQBySoHfwZcOygHeh4hoIpaeMAgkr5CGsKeuCjO7virI9ozbO9eN_HeuWEfdPpjepc87qhuVac0eTzuwlM/s1600/1.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihFjP3UnJ4iTX73FrLfhQofZzb_4VQxzCd34hunGSmFoVSYkw78xuxnDuknrnQBySoHfwZcOygHeh4hoIpaeMAgkr5CGsKeuCjO7virI9ozbO9eN_HeuWEfdPpjepc87qhuVac0eTzuwlM/s1600/1.PNG" /></a></div>
<br />
前兩行是排除不需改變Route規則的Url,然後只要將"~/Default.aspx"<br />
傳入RouteManager的Configure方法即可<br />
接著就新增首頁的Default.aspx檔案<br />
<br />
在Default.aspx的頁面中加入RouteManager與HolderSource控制項<br />
其中HolderSource可同時放入多個並且可以在部分HolderSource的HolderTemplate樣板中<br />
能再放入一層的單個RouteManager加多個HolderSource的組合,之後數層的規則一樣<br />
例如就像下面這樣具有到第三層的樹狀排列結構<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg79C7-DFXOYWMyghoQqirYZly9hZ8dJZ12-_ON0ydqZ251gwkki2ZaB1tpbrthixrzNnQ4yJ3prJVejY0yngikzYznIT9eogbJrTyi1InGVK2NjCSs_lHysH0SC9vSdQIAXiHqEpOROyTb/s1600/2.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg79C7-DFXOYWMyghoQqirYZly9hZ8dJZ12-_ON0ydqZ251gwkki2ZaB1tpbrthixrzNnQ4yJ3prJVejY0yngikzYznIT9eogbJrTyi1InGVK2NjCSs_lHysH0SC9vSdQIAXiHqEpOROyTb/s1600/2.PNG" /></a></div>
<br />
這樣就完成可以執行測試了<br />
<br />
RouteManager中只有一個DefaultLoadName屬性可以用來選擇RouteValue<br />
不符時預設顯示的HolderSource的ID<br />
然後HolderSource的ID則就是被用來與Url之中當RouteValue比對<br />
HolderSourceID與RouteValue相符就會顯示HolderTemplate的內容<br />
比如說瀏覽器網址是"http://localhost:25179/Index/"<br />
在上面的例子就會呈現Index這個HolderSource的樣板內容<br />
若網址導到是"http://localhost:25179/Home/"<br />
Index的樣板就不會呈現而改成呈現Home的樣版內容<br />
如果網址後面多加一個目錄變成"http://localhost:25179/Home/Page1/"<br />
那麼除了呈現Home的樣版內容外還會讓Home中Page1的樣版內容也一起呈現出來<br />
依此類推,這樣我們就可以利用Route控制網頁中控制項的呈現<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZRhFNJaYgKbCEu14rutMVtINEFLtAKC_ufb0naIVqTMMwBvNo-QeYQJehzeUxa-O700gcsQ1uaq2eOnOA9Qiv5bg0QhXKfeutA4N7TBp5xHbw0vmEbhFnEvY6cdaXqaz6Q0GMuCzsMGC/s1600/3.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZRhFNJaYgKbCEu14rutMVtINEFLtAKC_ufb0naIVqTMMwBvNo-QeYQJehzeUxa-O700gcsQ1uaq2eOnOA9Qiv5bg0QhXKfeutA4N7TBp5xHbw0vmEbhFnEvY6cdaXqaz6Q0GMuCzsMGC/s1600/3.PNG" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX0ssBpZJLAuYezwifPHbnnyJltWhXmzjXTNP72xpCdGN3mD1j0eI2h3E5XwifLgtlOtX7aF0CugkBvU8MMgU4Ph8EvEai5ucoyRDKKvFYSxzZXO7JXeWz5bUGYUkfuQA8LSjk3RE5KmhB/s1600/4.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX0ssBpZJLAuYezwifPHbnnyJltWhXmzjXTNP72xpCdGN3mD1j0eI2h3E5XwifLgtlOtX7aF0CugkBvU8MMgU4Ph8EvEai5ucoyRDKKvFYSxzZXO7JXeWz5bUGYUkfuQA8LSjk3RE5KmhB/s1600/4.PNG" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU2BfOJnnrpT7NntL-DbaOnhdbxIQFEQb6DyEhLw5CuNcCzVP6ZyYboUe6wZQJ_GGl1WcNw6t4GZjXtaTHk9SQrCpJ_3CXgEvXbciWRcDVHtoH250vqmvBr8Wve6MkL0lE8gvmTpyOaRt_/s1600/5.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU2BfOJnnrpT7NntL-DbaOnhdbxIQFEQb6DyEhLw5CuNcCzVP6ZyYboUe6wZQJ_GGl1WcNw6t4GZjXtaTHk9SQrCpJ_3CXgEvXbciWRcDVHtoH250vqmvBr8Wve6MkL0lE8gvmTpyOaRt_/s1600/5.PNG" /></a></div>
<br />
<br />
HolderSource也有個IsLoad屬性預設值是false用來控制樣版呈現,當樣版內容不呈現時<br />
不管裡面被放什麼控制項都不會被載入跟進入生命周期事件那麻煩的ViewState也就不會產生了<br />
RouteManager的工作就只是用Route物件比對Url,先算出自己在哪一層<br />
再找出應該要用來呈現的HolderSource將IsLoad變成true而已<br />
而且因為樣板裡面也能夠放入UserControl那些<br />
所以也可以視情況在UserControl中選擇再放入RouteManager與HolderSource進去<br />
只要總共不要超過10個的RouteValue就應該沒有問題了吧<br />
<br />JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-44632717783634690782013-09-15T20:31:00.002-07:002013-09-15T20:32:40.394-07:00技術的堅持和原則重要嗎?關於到底重不重要這個問題我覺得真的沒有很重要耶<br />
因為我覺得就算說多重要很多時候也只是被拿來說說而已<br />
否則我們也不會有這麼多有關技術債留下的難題了<br />
例如我就遇到過的:<br />
a.一個網頁表單的aspx.cs會出現包山包海的數千行程式碼(神物件)<br />
b.單一個存表單資料的資料表欄位能多達上百欄(反正規化?)<br />
c.某個App_Code中的套印類別居然用上三維陣列(可能在實做什麼演算法吧)<br />
d.網站首頁被放入複雜sql統計無cache直到有天流量尖峰使用者無法登入<br />
e.網站登入資訊頁在Page_Load直接呼叫外站服務無例外處理讓網站隨外站一起掛<br />
f.到處都是的SQL Injection弱點(真的可以執行sp_MsForEachTable逞罰)<br />
g.同事網站的登入資訊居然用靜態變數儲存,上線自己還抓不到BUG<br />
h.還有更多萬能的Session在控制項的事件中設定與讀取<br />
...<br />
還有許多,這些要列是列不完的<br />
有句話說"知識是有限的,只有愚蠢才是無限的"大概就是形容這些。<br />
但是我們也不能否認在獲得知識前無知的自己大概也曾經犯下過錯(或臨時的發蠢狀態XD)<br />
差別在每個人蠢的時間長度不同,有些人真的是橫寫的阿拉伯數字八阿<br />
<br />
可是這邊就產生了更奇怪的問題,而且對我們也許可能更加的重要<br />
"解決這些技術債的問題算聰明還是愚蠢呢?"<br />
我認為會有這些問題時表示技術的重要性已經有很大程度的被無視了<br />
這時候應該要考慮的是"你自己的位置"<br />
Position Yourself(<a href="http://st-threath.blogspot.tw/2013/09/position-yourself.html" target="_blank">http://st-threath.blogspot.tw/2013/09/position-yourself.html</a>)<br />
其實我是想分享這篇文章<br />
當技術在你身上,而你在這個地方(黑人騎馬真得很奇怪?...)<br />
會不會使你變得強勢還是繼續的弱勢你真的要想清楚<br />
<br />
以前我曾經有件任務要去修改一個ClassLibrary1.exe的專案<br />
這隻是個定期從外站服務撈取資料然後轉換存進系統資料庫的排程程式而已<br />
需要我在裡面加上在存進資料的同時過濾出可疑資料自動發信email給使用者的功能<br />
沒錯...這個專案名稱就是ClassLibrary1,新增類別庫專案時的預設名子(然後專案屬性被改成執行檔)<br />
可想而知裡面的程式碼根本無法維護,要不就是我能力太差吧<br />
沒有辦法,那時我就只好花了超出預定一點的時間去整個重寫這隻程式(不只是換個好名子啦XD)<br />
後來也只是被主管問到是不是程式重寫了而已,感覺不出很在意為什麼的樣子<br />
不過我也沒去多想...當然後來在那間公司還是有發生很多其他事情<br />
最後也離開了那裡,和那間公司最後的關係就是互相的逞罰吧...<br />
至於現在的我多少了解到關於真正的問題是出在哪裡<br />
<br />
我們不應該留在視對技術的堅持和原則為愚蠢的地方<br />
更重要的是要能更快的去查覺自己的位置、關於技術是被怎樣看待的<br />
自己的機會會在哪裡、是否有什麼方法可以改變它,那些多少都是有跡可循的(不知道就google公司名稱阿XD)<br />
又或者你的判斷是因為在其他地方有利所以可以讓步無所謂也罷<br />
最怕的是什麼都沒想,沒發現自己處在不允許任何堅持的劣勢<br />
那時再問對技術的原則與堅持重要嗎?<br />
吼,我自己舉自己的例子都覺得有點丟臉了啦>///<JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-74074729220782765762013-08-27T22:13:00.000-07:002013-09-25T16:55:08.602-07:00ASP.NET MVVM - ExtensionsControl (1)這兩天在ASP.NET MVVM Excalibur中加入了幾個使用者控制項
<br />
我一直在想有無好一點的方法去處理ViewModel對陣列集合資料的繫結功能
<br />
結果還是先把平日自己開發來經常使用在集合資料的控制項加進去了
<br />
以下是對這幾個控制項的介紹與示例程式
<br />
<br />
首先是FreeDataSource跟Pagination的功能<br />
<br />
1.FreeDataSource是一個資料來源控制項如同SqlDataSource,ObjectDataSource,EntityDataSource等一樣
用來搭配ListView,GridView,DataList..等等控制項呈現資料<br />
其特性是沒有其他限制,讓我們可以直接使用事件的回傳值當作資料來源<br />
無論在方法中回傳什麼也都盡可能讓它能支援分頁排序等功能<br />
例如下面的方法:
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizkPyAjn391Eh_9wR5N5OI4ubgBkCEbzI6vSWGkxdgEYcUPPd1kvyhL-aN4d7SuLC5e3jyQDpCDPBWbYZjQOuDjVUbp-lyOjP9cQ1B3WhB9xJSSjChQ72cl4tHqe4PJ8xjjphR6k9Rep6L/s1600/2.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizkPyAjn391Eh_9wR5N5OI4ubgBkCEbzI6vSWGkxdgEYcUPPd1kvyhL-aN4d7SuLC5e3jyQDpCDPBWbYZjQOuDjVUbp-lyOjP9cQ1B3WhB9xJSSjChQ72cl4tHqe4PJ8xjjphR6k9Rep6L/s1600/2.PNG" /></a></div>
就能直接讓回傳的IEnumerable物件資料用做DataBind的資料這樣<br />
<br />
2.Pagination是分頁用的控制項搭配FreeDataSource與DataPager製作分頁功能<br />
使用時需要在Pagination上指定PagerControlID以及在FreeDataSource上將PaginationControlID<br />
設定為該Pagination的ID<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZy0_tj94RTwfXoIOxeKTzK4lExDhOVFFcoPWF1w5O4DsvBbyN5DPMPEoOp5F-L12abfjaoY4NH2cX-qh_imrM2zmoi9wbEJQ1aBdYoVfYR3kERhtW-ahGkt073o9Iizs1MUGq88qCPDm7/s1600/3.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZy0_tj94RTwfXoIOxeKTzK4lExDhOVFFcoPWF1w5O4DsvBbyN5DPMPEoOp5F-L12abfjaoY4NH2cX-qh_imrM2zmoi9wbEJQ1aBdYoVfYR3kERhtW-ahGkt073o9Iizs1MUGq88qCPDm7/s1600/3.PNG" /></a></div>
<br />
執行結果:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikdNt_g9keqBFrqkTJFyartVBhSyl4Hbre0IcJIme_Pwv4l007eZ3A34vqKbl3fu6JfH0CadEJ7D-HnMUWCGhCNSwVGSfsdq8lwMrp6WoMccRg1OsmbZiw5OLJSWOZXet-5MQVn93zOEsk/s1600/4.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikdNt_g9keqBFrqkTJFyartVBhSyl4Hbre0IcJIme_Pwv4l007eZ3A34vqKbl3fu6JfH0CadEJ7D-HnMUWCGhCNSwVGSfsdq8lwMrp6WoMccRg1OsmbZiw5OLJSWOZXet-5MQVn93zOEsk/s1600/4.PNG" /></a></div>
<br />
順利完成分頁<br />
(其實還可以在FreeDataSource的方法中透過取得的頁數進行分頁處理)<br />
<br />
這裡主要是想當我們使用MVVM時可以讓ViewModel使用Binding去繫結FreeDataSource的OnExecuteSelected事件,然後就能將資料DataBind到要顯示資料的ListView或GridView上面,<br />
以達到控制Model資料的權責歸於ViewModel,與View的呈現邏輯分離<br />
<br />
另外還有加入PluralHolder, ContainerButton, HolderSource三個控制項<br />
是有關於控制動態樣板的功能,在編輯多筆資料時也許有用<br />
與示範程式一併都放在1.1.1.3版以後的專案範本中JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-62262071074829355472013-01-22T16:28:00.000-08:002013-01-22T22:29:39.309-08:00ASP.NET MVVM - ValueConverter<br />
最近MVVM新增的功能是關於Binding屬性(Property)間物件型別轉換的處理<br />
過去我們只是利用IConvertible介面在背後做簡易的轉換<br />
這在Web上沒有太大的問題,資料大多都為字串也就一直都沒處理例外<br />
只是最好的方式還是ViewModel與View上控制項屬性使用完全相同的屬性型別
<br />
不過今天新增了一個抽像類別ValueConverterBase
<br />
可以在當我們開發ViewModel時選擇為屬性(Property)添加Attribute
<br />
指定特定的ValueConverter轉換類別去處理型別轉換問題<br />
(當然沒有指定Attribute的屬性我們還是有利用IConvertible處理預設型別轉換)
<br />
<br />
以下是一個轉換屬性型別的範例<br />
當介面上TextBox輸入一個字元時,Binding到ViewModel可以轉成該字元ASCII號碼的int型態<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD0azCNA2HYT8nr8CQy2jxPEAIQebFYx5AJBVaotrttxk_K2HNSJ80F02mpxs8ByLZ_v2Kzc4UCf9xVg3H18mbbZ_UCbnmh-47d6e-smL0AHKLp60uJYYqoKGZ2cpVKPlohbTPQLEOxbAr/s1600/%E6%93%B7%E5%8F%96.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD0azCNA2HYT8nr8CQy2jxPEAIQebFYx5AJBVaotrttxk_K2HNSJ80F02mpxs8ByLZ_v2Kzc4UCf9xVg3H18mbbZ_UCbnmh-47d6e-smL0AHKLp60uJYYqoKGZ2cpVKPlohbTPQLEOxbAr/s640/%E6%93%B7%E5%8F%96.PNG" width="640" /></a></div>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2zOOMGCviK3paGyvRX8tt-aNIp08qTYTdVFVaK6JWBId9Uc6mTmLBURIn4_Cszh4QRu3biIIia1hNhbZEwFhL73O-6C3QkigL76zVaGg_S_gzgeDWgpTOkZv1V9SnzVdiYJm_1vHZUbzA/s1600/%E6%93%B7%E5%8F%962.PNG" imageanchor="1"><img border="0" height="410" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2zOOMGCviK3paGyvRX8tt-aNIp08qTYTdVFVaK6JWBId9Uc6mTmLBURIn4_Cszh4QRu3biIIia1hNhbZEwFhL73O-6C3QkigL76zVaGg_S_gzgeDWgpTOkZv1V9SnzVdiYJm_1vHZUbzA/s640/%E6%93%B7%E5%8F%962.PNG" width="640" /></a><br />
<br />
ASCIINumberValueConverter實做了ValueConverterBase中的兩個函式<br />
<br />
Convert(object value, out bool done)<br />
將傳入的value轉換成ViewModel所要的屬性型別(PropertyType),out done指出是否成功轉換<br />
<br />
ConvertBack(object value, Type targetType, out bool done)<br />
將傳入的value轉換回View上控制項原本的屬性型別(targetType),out done指出是否成功轉換<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE_XpOp2_xGH8BkspeUfFFqR80W4V7q6WSXLox8u-NQ5zz75Dt53zuzoeXyx_dB1IOksH1qCuo5DHief5U02STXMsRT-YKpFWnv9hypfiyz_h4vHAO6HN5a9UaOnRb-b1cEXCIN9Tpmt7d/s1600/%E6%93%B7%E5%8F%963.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE_XpOp2_xGH8BkspeUfFFqR80W4V7q6WSXLox8u-NQ5zz75Dt53zuzoeXyx_dB1IOksH1qCuo5DHief5U02STXMsRT-YKpFWnv9hypfiyz_h4vHAO6HN5a9UaOnRb-b1cEXCIN9Tpmt7d/s640/%E6%93%B7%E5%8F%963.PNG" width="640" /></a></div>
<br />
在屬性上設定ValueConverterAttribute由ASCIINumberValueConverter<br />
來處理Word這個屬性的型別轉換<br />
<br />
(附帶一提,ViewStateProperty是讓這屬性存放到ViewState中,65是預設值)JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-53960944969604225832012-03-23T01:00:00.001-07:002012-03-23T01:02:47.193-07:00ASP.NET Expression Package現在有一個可以用設計視窗在VS中編輯Expression語法的工具了<br />可以在每個ASP.NET控制項的Smart Tasks中自動加入一個[Edit Expression]按鈕<br />按下後就能開啟VS內建的Expression編輯視窗來編輯各種運算式的內容<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1cN2C0uGQSsHsTk1_oKAjFMTh2frKJSjU3YI8Dk857QOUmZfM61a7zSNa5_HP2h_rphQqFHm2-oj_wQ7QwQmneI1RRhRkqLMC8zMDjkB5UQ5RGqswBG1-q1BMIcfE2zxHwvTHIQn2utlJ/s1600/Package.png"><img style="cursor:pointer; cursor:hand;width: 400px; height: 213px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1cN2C0uGQSsHsTk1_oKAjFMTh2frKJSjU3YI8Dk857QOUmZfM61a7zSNa5_HP2h_rphQqFHm2-oj_wQ7QwQmneI1RRhRkqLMC8zMDjkB5UQ5RGqswBG1-q1BMIcfE2zxHwvTHIQn2utlJ/s400/Package.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5722999658971479186" /></a><br /><br />這是Visual Studio的外掛功能,需要安裝請到這裡下載<a href="http://visualstudiogallery.msdn.microsoft.com/f7e5e24a-1da3-4683-900d-a3c4ed927119">ASP.NET Excalibur Package</a>JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-40603916211763453072012-02-28T02:49:00.003-08:002012-02-28T02:58:02.605-08:00ASP.NET MVVM(3)往往我們系統不做分層架構的原因只是因為存在著某些單純的困難而已<br />因此現在的系統開發開始會利用越來越受人重視的像是ORM..等等的技術<br />所以現在MVVM也可以來個相似的Mapping功能囉^^<br /> <br />就來寫個示範,我們也沿用<a href="http://jurio-li.blogspot.com/2012/01/aspnet-mvvm-excalibur.html">第一篇文章</a>的範例<br />讓網頁上有一個文字方塊與按鈕,可以輸入名子按下按鈕後在文字方塊下方,顯示輸入的名子<br /> <br />1.建立View的Default3.aspx檔案,內容如下<br /><br /><pre><%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default3.aspx.cs" Inherits="Default3" %><br /><br /><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br /><html xmlns="http://www.w3.org/1999/xhtml"><br /><head runat="server"><br /> <title>MVVM By Auto ViewModel Base</title><br /></head><br /><body><br /> <form id="form1" runat="server"><br /> <div><br /> 請輸入您的大名:<asp:TextBox ID="TextBox1" runat="server" Text="<%$ Binding: Name %>"></asp:TextBox><br /> <asp:Button ID="Button1" runat="server" Text="確定" OnClick="<%$ Binding: Button1_Click %>" /><br /><br /> <br /><br /> <asp:Label ID="Label1" runat="server" Text="<%$ Binding: Text %>"></asp:Label><br /> </div><br /> </form><br /></body><br /></html></pre><br /><br /><br />2.完成View後,就按下Visual Studio的建置方案(F6)對網站進行一次編譯,等建置成功,然後在方案總管中<br />用滑鼠對方案目錄進行->滑鼠右鍵->重新整理資料夾<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizMQGQONzSmc9Kpccvl6fUqKdEhYa-Cn1cxMRnR38qSlJmjL7pI1TTUe0An1iPHEhi4HyzEUddqgc26e5t4huzBdgxdAZl8VYgKDfntvboIgrNwti9DLJEwsl5H_QZuFVHou7mfI4Y9lgX/s1600/MVVM+%25283%2529.png"><img style="cursor:pointer; cursor:hand;width: 255px; height: 161px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizMQGQONzSmc9Kpccvl6fUqKdEhYa-Cn1cxMRnR38qSlJmjL7pI1TTUe0An1iPHEhi4HyzEUddqgc26e5t4huzBdgxdAZl8VYgKDfntvboIgrNwti9DLJEwsl5H_QZuFVHou7mfI4Y9lgX/s400/MVVM+%25283%2529.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5714138595331585362" /></a><br /><br />我們馬上立即就能夠發現在App_Code中多了一些目錄與類別檔案,像此次的ViewModel/Base/Default3.cs<br />這個就是MVVM針對Default3自動產生的ViewModel基底類別,<br />類別裡面已經實做了在View中所有被Binding使用到的所有屬性與EventMethod,只等我們繼承引用而已<br />(這些class是不需要改它的,每次View有變動後就會重新產生一次)<br /> <br />3.製作ViewModel,在方案總管加入新項目Hello3.ascx至網站中,撰寫Hello3.ascx.cs的內容<br />將原本繼承的UserControl改為新的基底類別ViewModel.Base.Default3<br />接著使用override關鍵字帶出Button1_Click方法並撰寫其功能程式,如下<br /><br /><pre>using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Web;<br />using System.Web.UI;<br />using System.Web.UI.WebControls;<br /><br />public partial class ViewModel_Hello3 : ViewModel.Base.Default3<br />{<br /> protected void Page_Load(object sender, EventArgs e)<br /> {<br /><br /> }<br /> public override void Button1_Click(object sender, EventArgs e)<br /> {<br /> if (Name != "")<br /> {<br /> Text = Name + ",您好。";<br /> }<br /> else<br /> {<br /> Text = "請輸入名字";<br /> }<br /> base.Button1_Click(sender, e);<br /> }<br />}</pre><br /><br />4.將ViewModel放進View中,如下,這樣就完成囉。<br /><br /><pre><%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default3.aspx.cs" Inherits="Default3" %><br /><br /><%@ Register Src="ViewModel/Hello3.ascx" TagName="Hello3" TagPrefix="uc1" %><br /><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br /><html xmlns="http://www.w3.org/1999/xhtml"><br /><head runat="server"><br /> <title>MVVM By Auto ViewModel Base</title><br /></head><br /><body><br /> <form id="form1" runat="server"><br /> <div><br /> <uc1:Hello3 ID="ViewModel" runat="server" /><br /> 請輸入您的大名:<asp:TextBox ID="TextBox1" runat="server" Text="<%$ Binding: Name %>"></asp:TextBox><br /> <asp:Button ID="Button1" runat="server" Text="確定" OnClick="<%$ Binding: Button1_Click %>" /><br /><br /> <br /><br /> <asp:Label ID="Label1" runat="server" Text="<%$ Binding: Text %>"></asp:Label><br /> </div><br /> </form><br /></body><br /></html></pre><br /><br />另外一提,不知道有寫過Android App的人有沒有覺得這樣就很像R.java了呢,只不過不是靜態XD<br /> <br />詳細範例與程式碼下載連結於<a href="http://jurio-li.blogspot.com/2011/05/aspnet-flash-excalibur-10-release.html">公告文章(Download)</a>中JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-11991125140945534512012-02-26T00:08:00.002-08:002012-04-30T21:51:47.472-07:00ASP.NET MVVM(2)微軟在XAML上的Binding與ViewModel的概念真的非常特別<br />
雖然ASP.NET是網站型態會受限於程式需要PostBack的方式才能執行<br />
但Web Form的控制項必然與他有一定的共通點...畢竟我們有很多案件的開發需求還是在Web上進行<br />
所以我們就繼續的借用一些新的東西來用吧XD哈哈<br />
<br />
Expression語法新增加的功能是ID與Type 的指定,以及Property對Method的繫結<br />
<br />
(1)語法上加入逗號將繫結屬性名稱外可再選擇性的在加上ID或Type等於某控制項的方式,這樣以後此控制項Binding時就不會去以原本的ViewModel為對象而是用ID或型別去尋找出該條件的對象做繫結,而且這個尋找方式有向上延伸的功能,也就是往上控制項階層進行尋找<br />
例如用在UserControl中也就可以因為設定了Panel的Type而讓UserControl因放置的Panel不同而有不同結果<br />
<br />
(2)原本的繫結名稱可以用繫結對象Method的名子來做設定,只要繫結對象(ViewModel)有公用符合名稱並且有回傳值無參數的方法即可<br />
<br />
(3)語法上可以使用Mode等於去設定繫結方式<br />
Default:預設值,會自行判斷如果使用ViewModel則用雙向,若是指定控制項ID或Type則預設為單向<br />
OneWay:單向,只會在目標屬性設定繫結對象的屬性值,不會改變繫結對象屬性值<br />
TwoWay:雙向,目標屬性改變時也會同時更變繫結對象屬性<br />
<br />
以下是程式示範<br />
<br />
1.Default3.aspx<br />
<br />
<pre><%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default3.aspx.cs" Inherits="Default3" %></pre>
<br />
<pre><%@ Register Src="UserControl.ascx" TagName="UserControl" TagPrefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "<a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</a>">
<html xmlns="<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>">
<head runat="server">
<title>Bind Control & Method</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:UserControl ID="UserControl1" runat="server" />
<asp:Label ID="Label1" runat="server" Text='<%$ Binding : ID = UserControl1, GetText %>'></asp:Label>
<asp:Panel ID="Panel1" runat="server" ToolTip="456">
<asp:Label ID="Label2" runat="server" Text='<%$ Binding : Type = Panel, ToolTip %>'></asp:Label>
</asp:Panel>
<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="true" Text="789"></asp:TextBox>
<asp:Label ID="Label3" runat="server" Text='<%$ Binding : ID = TextBox1, Mode = OneWay , Text %>'></asp:Label>
<%-- Mode => Default, OneWay, TwoWay --%>
</div>
</form>
</body>
</html></pre>
<br /><br />
2.UserControl.ascx.cs<br />
<br />
<pre>using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class UserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public string GetText()
{
return "123";
}
}</pre>JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-29180060525919491412012-01-23T12:21:00.001-08:002012-02-26T00:11:35.044-08:00ASP.NET MVVM(1)MVVM是Model-View-ViewModel的縮寫<br />基本上也是一種程式系統分層的架構:<br />Model負責資料。<br />View負責呈現介面。<br />ViewModel則是前兩者間互動的媒介。<br />介面不能直接驅動資料,必須由ViewModel負責<br />詳細相關介紹可以閱讀這篇文章<br />http://blog.sanc.idv.tw/2011/12/wpf-mvvm.html<br /><br />在ASP.NET MVVM裡面Excalibur將透過利用ASP.NET的Expression語法讓Web Form同樣做出類似WPF MVVM的架構,先來一個示範,請看看囉<br /><br />1.首先網站的web.config要加進Excalibur的設定,註冊好'Binding'這個Expression語法需交由Excalibur的類別處理,(當然Bin裡面dll等等,那些也要放進去)<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgreUxTs02_9-_cZGZzqFWwVAFF-mewFZ2GxCSWPKr0Y5wPt4TsUzNrr3azbqSoIsAnsyd_3mSkjV-qeVKgZEz5pDKZ4BlSrDPCbj3EaOyZOSaaKt0BIwcSsu1h1w410rqEswf9rXg9szJf/s1600/MVVM%25280%2529.png"><img style="width: 400px; height: 60px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5700925521745374354" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgreUxTs02_9-_cZGZzqFWwVAFF-mewFZ2GxCSWPKr0Y5wPt4TsUzNrr3azbqSoIsAnsyd_3mSkjV-qeVKgZEz5pDKZ4BlSrDPCbj3EaOyZOSaaKt0BIwcSsu1h1w410rqEswf9rXg9szJf/s400/MVVM%25280%2529.png" /></a><br /><br />然後我們做一個示範功能好了,只要一個網頁上有一個文字方塊與按鈕,可以輸入名子按下按鈕後在文字方塊下方,顯示輸入的名子即可,像下面這樣<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoqlRTHwkR_fKdlyaUQ5fxVbSXSZ3yDK85G2UFhj2tcPY1zoFyP3nd0EV3oEXyk9hWCZ22dVVJufWjPWGOiAbU1tzqXJOvKU3Hs0qldVhvWdzEmR2nLOMrsafeZvkeygHIMyBTeFsAhw92/s1600/MVVM%25281%2529.png"><img style="width: 400px; height: 102px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5700925523358384578" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoqlRTHwkR_fKdlyaUQ5fxVbSXSZ3yDK85G2UFhj2tcPY1zoFyP3nd0EV3oEXyk9hWCZ22dVVJufWjPWGOiAbU1tzqXJOvKU3Hs0qldVhvWdzEmR2nLOMrsafeZvkeygHIMyBTeFsAhw92/s400/MVVM%25281%2529.png" /></a><br /><br />2.在方案總管加入新項目Default.aspx至網站中,然後於設計的原始檔中加入各一個TextBox、Button、Label,調整並加入Binding語法如下<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihrBhIFGq-P1jGbNSuyt052vzX-snNF0VPjm0k8Q1WCn72ptEHrVWkHGyGaL4-SZ0qgJkLR23PsRed5NcUb1TA6dslzsY4sBs3GiLs-wOsaK1svH0AFYsPpQUXaEJ-aGBa4g6zO98l-K_9/s1600/MVVM%25282%2529.png"><img style="width: 400px; height: 159px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5700925530704311602" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihrBhIFGq-P1jGbNSuyt052vzX-snNF0VPjm0k8Q1WCn72ptEHrVWkHGyGaL4-SZ0qgJkLR23PsRed5NcUb1TA6dslzsY4sBs3GiLs-wOsaK1svH0AFYsPpQUXaEJ-aGBa4g6zO98l-K_9/s400/MVVM%25282%2529.png" /></a><br /><br />這樣就幾乎完成MVVM其中的View了,要改變做法的是使用Binding,Binding裡面的文字意思就是View要繫結到ViewModel中的屬性名稱,而且這邊就連像OnClick這樣的event也可以透過Binding去繫結ViewModel裡面的method了,所以,至於Default.aspx.cs中的程式就一行都不需要去動它了,因為View不做其他事情<br /><br />3.接下來要製作ViewModel的部分,在方案總管加入新項目Hello.ascx至網站中,因為示範的功能很小Model的部分就先用一個Label控制項來充當省略囉,Hello.ascx設計如下<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ8cZpqclzaz-zZPSATa8Va_8uFkRASVihaTKdD-VvKrgauQPACy40fEQ2XeDXyQOO81idvh7-JMAhQoPyKFZ_Wpa3FCG25qUbn2NGI0nvKI_tHIL_SlzBS_EmGj_ddW611P94_ldS8P-y/s1600/MVVM%25283%2529.png"><img style="width: 400px; height: 28px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5700925537930541842" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ8cZpqclzaz-zZPSATa8Va_8uFkRASVihaTKdD-VvKrgauQPACy40fEQ2XeDXyQOO81idvh7-JMAhQoPyKFZ_Wpa3FCG25qUbn2NGI0nvKI_tHIL_SlzBS_EmGj_ddW611P94_ldS8P-y/s400/MVVM%25283%2529.png" /></a><br /><br />4.撰寫Hello.ascx.cs的內容,分別完成Name屬性與Button1_Click方法中的程式,如下<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8ECG6d3TPNPc4RizLXStYVKi7aGVbCJjp2EIvUKTe7Ipqy8Nm1f4YK2JlqOx9NHHy-rPvEbv_pxf8yhQoIALkK91HIjPMAshv-gRuKRb77-6biG-DLZTpVWNSdfHh-pYBQbVeBwGfvGQ1/s1600/MVVM%25284%2529.png"><img style="width: 400px; height: 362px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5700925544356094130" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8ECG6d3TPNPc4RizLXStYVKi7aGVbCJjp2EIvUKTe7Ipqy8Nm1f4YK2JlqOx9NHHy-rPvEbv_pxf8yhQoIALkK91HIjPMAshv-gRuKRb77-6biG-DLZTpVWNSdfHh-pYBQbVeBwGfvGQ1/s400/MVVM%25284%2529.png" /></a><br /><br />到這裡一定要說明Hello.ascx的兩個地方:<br /><br />(1)為何Label的ID屬性要設為'Model'?<br /><br />答:是因為要有簡單的方式當做MVVM架構中Model物件的識別,或者如果有其他需求也有另一個方法可以在程式中實做IViewModel介面,指派其他或者不是控制項的物件做為Model。所以另外同樣的在View中也是用相同的規則,會用ID為ViewModel的控制項或實做IView介面,後指派的結果讓MVVM架構識別ViewModel物件<br /><br />(2)為何View裡面Binding的Text屬性不用實做出來?<br /><br />答:這是因為使用了幫ViewModel節省程式碼的機制,屬性名稱相同ViewModel就不用另外去寫轉譯Model的屬性到ViewModel上的程式,因為在View上Binding的規則是,如果ViewModel沒有這個屬性就允許透過去Binding裡面Model的屬性,因此只要屬性不是Binding在雙向的目標上,只是要唯讀呈現就可使用,否則不建議喔<br /><br />5.最後終於要將ViewModel跟View結合起來了,到Default.aspx的設計頁面將Hello.ascx自方案總管拖曳進來,然後修改控制項ID為ViewModel,如下,建置成功,就完成囉<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6sPkQMHqcEzxujalrByIU5d8VhYKdOCkVIYAIc9cP5U5HCHJHW1AtVbpCo0pD8YNDfUzvnmhBtaIucDoDeNTeR3h2FlSx4HdiBT6IFg8bGLEqLnKNj-IElyHtoXobt_FQeY7E6SbL_i4a/s1600/MVVM%25285%2529.png"><img style="width: 400px; height: 163px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5700925623655644786" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6sPkQMHqcEzxujalrByIU5d8VhYKdOCkVIYAIc9cP5U5HCHJHW1AtVbpCo0pD8YNDfUzvnmhBtaIucDoDeNTeR3h2FlSx4HdiBT6IFg8bGLEqLnKNj-IElyHtoXobt_FQeY7E6SbL_i4a/s400/MVVM%25285%2529.png" /></a><br /><br />Default.aspx.cs<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCs_-VpRytbXRLgOOMaDEWeMoT7PXbDBKG8FweyZNI-oqKW_oSgnntCRN2Q500rhUW0b5BmP9Z8bMstdNQeOYOPzCzb9buMIe0WzbtLDARNnnMrN8k_z7ed7Pk-wEaQfsO8KgpcVP_RLGP/s1600/MVVM%25286%2529.png"><img style="cursor:pointer; cursor:hand;width: 400px; height: 187px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCs_-VpRytbXRLgOOMaDEWeMoT7PXbDBKG8FweyZNI-oqKW_oSgnntCRN2Q500rhUW0b5BmP9Z8bMstdNQeOYOPzCzb9buMIe0WzbtLDARNnnMrN8k_z7ed7Pk-wEaQfsO8KgpcVP_RLGP/s400/MVVM%25286%2529.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5700929935528832850" /></a><br /><br />詳細範例與程式碼下載連結於公告文章中JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-91631789158000906462011-05-16T01:38:00.001-07:002020-10-17T10:53:49.249-07:00ASP.NET MVVM Excalibur 1.1 - Release<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiplXQzzvBOBpyhPGmgLcyXwp2d2Ue7EdYYBEwy89gc1E1qm8qiiC03DC4W4ISFfQVp0IKheiS7BoaYOso3IyyBO2Cq47zYQ1Eb41jTkbmijmSUJ03yPr6j_gGHnrpVV4AlQn55KAjRsoq-/s1600/VSIX.png" />
Excalibur.Web 1.1.9.3<br />
<br />
<a href="https://marketplace.visualstudio.com/items?itemName=Jurio-Li.ASPNETMVVMExcalibur-9198">下載處(Download)</a> - 2020/10/18<br />
<br />
2020/10/18 : 擴充控制項新增DataBound事件,修正Binding屬性值於事件DataBind控制項後復原問題<br />
2019/06/15 : 修正Excalibur.Scabbard在未設定Port時因TimeWait佔用過多尋找不到FreePort的錯誤<br />
2019/02/23 : 新增IView擴充方法ReBindingViewEvents,可用於IView變更ViewModel時重新繫結事件<br />
2018/12/02 : 新增ScabbardSessionStateStore類別,可於config設定Session以共用快取Cache存放<br />
2018/07/04 : 修正FreeDataSource控制項在使用DataView資料來源做排序含Null值時產生的錯誤<br />
2018/06/25 : 修正Binding語法使用在具有多個postDataKey的控制項時發生的錯誤ex:CheckBoxList<br />
2018/05/08 : Extensions.Web.UI.UserControl新增SortExpression屬性與Sort方法,提供排序使用<br />
2018/04/29 : 修改PluralHolder於ExtractAllValues型別不符時帶出Null值而不產生例外<br />
2018/01/06 : 新增VirtualPathAttribute類別,可尋找並取得UserControl虛擬路徑的類別Attribute<br />
2017/06/18 : 改進ViewStatePropertyAttribute處理效能及DefaultValue屬性Page使用問題<br />
2017/02/26 : 增加ComponentOperator類別的方法,可支援非public型別使用<br />
2016/09/24 : 新增Extensions.Web.Serialization.ObjectStateFormatter序列化型別<br />
2016/07/30 : 修改Binding機制,使PostBack時Load於稍後的RaiseChangedEvents讀取更新資料<br />
2016/05/14 : CacheExtensions.GetProvider加入連線參數,以AppDomainAssemblyBinder加強反序列化<br />
2016/04/01 : 修正ViewStatePropertyAttribute的DefaultValue屬性在非擴充UserControl使用的問題<br />
2016/03/18 : 繫結Binding增加可使用!Expression驚嘆號取得相反布林值語法功能<br />
2016/03/12 : 修正Excalibur.Scabbard.exe在VS網站開發伺服器不會隱藏及強制關閉後無法重開的問題<br />
2016/02/13 : 加入自動啟動的Excalibur.Scabbard.exe服務,管理網站共用快取Cache資源<br />
2015/07/02 : PluralHolder控制項可使用DataSourceID綁定資料來源控制項,並新增ExtractAllValues方法<br />
2015/07/02 : 修改Binding以支援繫結控制項的IStateManager子物件Property(控制項在樣板內未支援)<br />
2015/04/13 : 對Page,MasterPage,UserControl增加擴充方法SendMessage,GetControlMessageCenter<br />
2015/04/11 : 置換ViewStatePropertyAttribute命名空間並使其支援於Page,MasterPage中使用<br />
2015/03/10 : 修正FreeDataSource查詢事件以yield return產生重複執行錯誤並支援DataView資料來源<br />
2015/03/10 : 修正Binding繫結在部分動態載入控制項的情況AutoPostBack無法觸發事件問題<br />
2015/03/07 : 修改ExtensionsConfigSection設定類別,增加PageAdapter.SetEnableCachePageViewState<br />
2015/03/07 : 支援.net3.5的版本,除了3.5不相容功能以外,例如Route,dynamic等<br />
2014/10/03 : 加入CommandProvider類別與Raise及Send方法,用於預先定義通知事件的方法指令型別<br />
2014/08/12 : 擴充控制項中加入BubbleEventMethodAttribute與RaiseBubbleEvent方法簡化氣泡事件使用<br />
2014/08/12 : 增加ContainerButton的Container選項,HtmlGeneric可搭配TagName屬性指定其他Html容器<br />
2014/04/02 : 修改GuidCachePageStatePersister類別合併減少ViewState使用的Cache數量<br />
2014/03/08 : 修改事件繫結時的處理方法,使支援具有部分提供參數相等的方法(參數名稱與類別)<br />
2014/02/28 : 新增IViewBindingsAccessor介面並使Binding繫結支援ExpandoObject等dynamic物件<br />
2013/12/20 : 當Binding繫結在ViewModel,Model中找不到屬性或未加入ViewModel則直接繫結View屬性<br />
2013/12/20 : 新增UpdatePanelAutoBindingAttribute屬性類別可控制關閉UpdatePanel更新<br />
2013/11/27 : 使ReloadToManagedRoute方法加入傳遞物件資料至ViewModel功能<br />
2013/11/22 : 在UpdatePanelAdapter中加入OnUnload例外問題處理<br />
2013/11/05 : 修改HolderSource的AppendUpdatePanel屬性部分問題<br />
2013/10/22 : 加入ReloadToManagedRoute方法使RouteManager可以不需重導Url並更新頁面<br />
2013/10/21 : 修正因為控制項放置順序導致OneWay繫結屬性不正確的問題<br />
2013/10/13 : 新增MessageNotifyMethodAttribute,簡化MessageNotify使用<br />
2013/10/10 : 增加Message的DataBoundControlHelper並加入MessageArgument的屬性繫結支援<br />
2013/10/06 : 擴充使用者控制項新增SendMessage方法與MessageNotify接收訊息事件<br />
2013/09/25 : 加入RouteManager擴充控制項與示範程式<br />
2013/08/27 : 加入ExtensionsControl的5個擴充使用者控制項與示範程式<br />
2013/07/27 : BindingExpressionEditor設計UI屬性加入下拉選單功能<br />
2013/07/17 : 增進Property的Binding Expression效率,修改Reflection相關方法<br />
2013/06/23 : 序列化物件比較由XmlSerializer改為BinaryFormatter支援<br />
2013/06/22 : 在擴充UserControl中新增dynamic型態的ViewBag屬性,等同使用ViewState<br />
2013/06/16 : 對預設的ValueConverter增加處理Nullable型別的能力<br />
2013/06/13 : 修正對Nullable屬性無法使用繫結的錯誤<br />
2013/05/31 : 對預設的ValueConverter增加處理Enum型別的能力<br />
2013/05/07 : 新增BubbleEventExtensions控制項氣泡事件相關擴充函式<br />
2013/04/04 : 修正對ViewModel屬性為序列化參考物件的型別時能夠更正確的支援<br />
2013/03/27 : Binding繫結可用於runat="server"控制項的data-xxx等任何Html屬性了<br />
2013/03/27 : 繫結語法加入Argument設定給予ViewModelMaker使用<br />
2013/03/20 : 修改新增ViewModelMaker相關類別,修正編譯錯誤<br />
2013/03/05 : 修正對自訂控制項的泛型屬性無法使用繫結的錯誤(1.1發佈)<br />
2013/03/02 : 新增IValueConverter介面,增加ValueConverterAttribute參數給予ValueConverter建構式<br />
2013/03/01 : 使TwoWay Binding的控制項屬性不再限定只繫結前端PostBack值,可適用後端事件變更值<br />
2013/02/23 : 新增IFindControlProvider介面,可以在控制項中調整DataBoundControlHelper的部分過程<br />
2013/02/23 : Binding Expression增加Life=Load,PreRender選項讓繫結可選擇提前發生<br />
2013/01/20 : 新增ValueConverterBase與ValueConverterAttribute類別,建立轉型處理<br />
2013/01/17 : 刪除App_Browsers資料夾必要,改由DLL自動註冊ControlAdapter<br />
2013/01/07 : Extensions.Web.UI.UserControl新加IsPostBack以判斷控制項是否不是第一次載入<br />
2012/12/29 : 修改disabledViewModelMaker預設值為true不開啟,新增ViewStatePropertyAttribute<br />
2012/09/16 : 強化Binding語法可對子屬性繫結(ex:Binding List.Count)<br />
2012/07/04 : web.config增加disabledViewModelMaker設定可選擇關閉ViewModelMaker功能<br />
2012/04/21 : 解決IPostBackDataHandler控制項於控制項樣板中繫結問題<br />
2012/04/17 : 修正UserControl繫結發生物件不符合目標型別錯誤<br />
2012/04/05 : 加入IServiceProvider的屬性繫結支援<br />
2012/03/23 : 修改設計類別與完成Excalibur.Package的VS外掛以便設計控制項的Expression<br />
2012/03/15 : 加入BindingExpressionEditor設計類別<br />
2012/03/13 : 新增BehaviorControl與EventTriggerControl基底類別<br />
2012/03/09 : Binding去除屬性繫結需IAttributeAccessor控制項限制(僅剩事件繫結)<br />
2012/03/08 : ViewModel的NamingContainer區隔在MasterPage下問題修正<br />
2012/03/02 : Expression可設定Mode=Default,OneWay,TwoWay的不同方式<br />
2012/03/01 : 修正判斷AsyncPostBackTrigger需符合EventHandler<br />
2012/02/28 : 加入ViewModelMaker功能機制當每次建置網站時將自動產生ViewModel的基底類別<br />
2012/02/26 : 繫結Property支援IConvertible轉型<br />
2012/02/25 : BindingExpression可設定Control的ID或父層特定Type,以及支援屬性繫結到Method<br />
2012/02/12 : ViewModel修改考慮NamingContainer區隔,繫結屬性可唯獨或唯寫<br />
2012/01/30 : Binding加入自動使UpdatePanel加入AsyncPostBackTrigger判斷<br />
2012/01/24 : (pm22)修正Binding於UserControl下xml編譯錯誤<br />
2012/01/24 : ASP.NET MVVM 發佈(BindingExpressionBuilder)<br />
2011/12/05 : 增加DescriptorDataItemContainer類別<br />
2011/07/17 : 增加ComponentOperator取代Reflection(.NET4.0版本,3.5以下無法使用)<br />
2011/06/22 : 修正swc組件Bug(Component)<a href="http://jurio.myweb.hinet.net/ASP.NET%20Flash%20Excalibur1.0-Release(20110622).rar">Release-1.0.3.1</a><br />
2011/06/17 : 增加Flash.Web.UI.UserControl的Event(Create)<br />
2011/05/31 : 修改swc組件初始方法<br />
2011/05/16 : 1.0發佈JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-36651710158362588472011-04-24T05:28:00.000-07:002011-05-19T18:45:05.487-07:00ASP.NET Flash Excalibur 1.0 – Part 2這一篇要說明ASP.NET Flash Excalibur怎麼將資料回傳,讓Flash能與Web上的程式互動。<br /><br />首先建立一個後端的Listen,接收一個輸入文字的內容然後儲存在網站上,保留下次再開啟時可以顯示出來。步驟:<br /><br />1.一樣建立UserControl,並撰寫程式碼如下。<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1-Y-V2Q4KBJJfmoWDuLuhR5Wk_N-4Ep8elQwXF6sfjHiqiCFUhH9xJeY9Qqe4zVcDihVBhmuFAZT1sjZ03Viv2_XL8PTBMpAqvSNx9HTHiszoguLcg1rkU_tc3K9LvfzBKNJRmxsgyJXN/s1600/image001.png"><img style="WIDTH: 400px; HEIGHT: 213px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5599126451788031762" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1-Y-V2Q4KBJJfmoWDuLuhR5Wk_N-4Ep8elQwXF6sfjHiqiCFUhH9xJeY9Qqe4zVcDihVBhmuFAZT1sjZ03Viv2_XL8PTBMpAqvSNx9HTHiszoguLcg1rkU_tc3K9LvfzBKNJRmxsgyJXN/s400/image001.png" /></a><br />解說一下,主要在第24行的程式: <br /><br />this.Listen["Save"].Listen += new OnListen(Save_Listen); <br /><br />這裡是我們要註冊給Flash前端呼叫的方法,名子是”Save”,當被Flash呼叫時就是要控制項執行指定的Save_Listen方法,只要用這樣的方式就可以在各個控制項中註冊多個能被前端呼叫的Listen,而e.Value在Flash中是用Binder組件對輸入文字做繫結,所以其資料就是回傳前端所填寫或改變的內容。<br /><br />另外關於e.Value註冊的變數有給它一個限制,其必須在控制項的OnCreate中有給值的變數名稱才可在Listen中被使用,否則執行時將會引發錯誤。<br /><br />2.建立Flash(AS3)檔,放置一個動態文字並設為可編輯的,實體名稱設為cache。<br /><br />3.加入FlashRemoting與Binder組件,並給予FlashRemoting實體名稱為Remoting,接著設定組件參數FlashRemoting的controlPath值設為~/CacheText.ascx,Binder的bindName值設為CacheText,bindProperty值設為cache.text。<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg963wCWCRs-ld4j7_8v-Rso-cQjstAutPB60FbkbI4TwRskud9lWQPo6ukFhpW5H_wi-Dz-NJiW4TFEjI6K4yzpBIBd-GRMI3rLSLr2npnSYyYsTzBfmaah5gd-2kJ7KHt3mnhXFvfGPkc/s1600/image003.png"><img style="WIDTH: 400px; HEIGHT: 213px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5599126457041058130" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg963wCWCRs-ld4j7_8v-Rso-cQjstAutPB60FbkbI4TwRskud9lWQPo6ukFhpW5H_wi-Dz-NJiW4TFEjI6K4yzpBIBd-GRMI3rLSLr2npnSYyYsTzBfmaah5gd-2kJ7KHt3mnhXFvfGPkc/s400/image003.png" /></a><br />4.加入一個按鈕元件實體名稱為SaveButton,然後於影格撰寫按鈕動作程式碼如下。<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpmriGsnOd5KjVDUL76iceDz56nBXMWVe0gSzK59x8rHAR9lWxN_ycovWbl5LowXoX4bcEmPgkmWx4Fc4z01rF4Ba_hgmr9_Ref3Fqdd3TqyLa_uo4i-uacuxdrB_pIp3eKACF8sFohn_4/s1600/image005.png"><img style="WIDTH: 400px; HEIGHT: 248px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5599126458102471378" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpmriGsnOd5KjVDUL76iceDz56nBXMWVe0gSzK59x8rHAR9lWxN_ycovWbl5LowXoX4bcEmPgkmWx4Fc4z01rF4Ba_hgmr9_Ref3Fqdd3TqyLa_uo4i-uacuxdrB_pIp3eKACF8sFohn_4/s400/image005.png" /></a><br />5.最後測試影片就完成囉,可以修改文字內容儲存於網站上,關閉重複測試影片就會看到前次有儲存的內容。<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVe4lJ4cTejvWYPjJAziSbF3wDq8iiFldOg3dNpP_MVsktg73K6ZsFc8cUFfCk0-x7mTNROcrCF-RVMTd3KaFA2Ok6hZ3g0ooUFRtFfOBSajwElkqTKJVYE07HgscpsM2nfqxKwg8Z24Wl/s1600/image007.png"><img style="WIDTH: 400px; HEIGHT: 324px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5599126458748659362" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVe4lJ4cTejvWYPjJAziSbF3wDq8iiFldOg3dNpP_MVsktg73K6ZsFc8cUFfCk0-x7mTNROcrCF-RVMTd3KaFA2Ok6hZ3g0ooUFRtFfOBSajwElkqTKJVYE07HgscpsM2nfqxKwg8Z24Wl/s400/image007.png" /></a><br />到這裡很明顯的前端只要簡單的呼叫FlashRemoting的SendEvent函式,傳入要執行的Listen名稱就能與Web達成互動,同樣如果當後端在Listen中改變e.Value的值以後,結果也會被Binder同步在前端繫結的目標上。<br /><br />概念就有點類似動態網頁的Submit一樣,不會很難對吧。<br /><br />接下來,下一篇會有個較進階的範例來示範如何應用Flash的元件與UserControl的父子階層。JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0tag:blogger.com,1999:blog-4199750673650793927.post-35417962236678161012011-03-14T23:46:00.000-07:002011-05-19T18:44:41.340-07:00ASP.NET Flash Excalibur 1.0 - Part 1<span style="font-size:85%;">ASP.NET Flash Excalibur是一個在ASP.NET上整合開發Flash互動網站的框架,開發人員將獲得更貼近已往Web Form的開發方式,很容易就能向前端Flash程式做資料與狀態的連結,同時減少設計師在Action Script程式處理上的難度。<br /><br />廢話不多說,首先來個Hello World示範吧:<br /><br />1.在ASP.NET網站建立一個新的UserControl,置換基底類別並撰寫程式碼如下。<br /></span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDNb3Rii87rdJ8IqyziAPhcFDQ4tmCYL_I-egizRFhjXTR3y-tVYOhodXXJh_45BxQWY_lXJ5Vl3NHHGBESe67A_fJlJzioIfgoI9e6F0KSqNm29tTrKg8Wxtl-I6FDlDbrYSLsQJMPlbD/s1600/image001.png"><span style="font-size:85%;"><img style="WIDTH: 400px; HEIGHT: 213px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5584196587117722530" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDNb3Rii87rdJ8IqyziAPhcFDQ4tmCYL_I-egizRFhjXTR3y-tVYOhodXXJh_45BxQWY_lXJ5Vl3NHHGBESe67A_fJlJzioIfgoI9e6F0KSqNm29tTrKg8Wxtl-I6FDlDbrYSLsQJMPlbD/s400/image001.png" /></span></a><span style="font-size:85%;"><br />2.開啟Flash CS4建立空白Flash(AS3)檔,並放置一個動態文字,實體名稱設定為myFirst。<br /></span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrY3l1EF-LjnBUH2PI0F7Vn71dpJM9Plft25uptCxdqhdF3wVjaTqblE0UwRVlKlhKzkkxR2cjmIJ3pYQ7yzQyywQWxpYBBG0C4zDIn8LMVjYLHMHTmAkVmIwRIWk8cb2cY91e9LKEP12U/s1600/image003.png"><span style="font-size:85%;"><img style="WIDTH: 400px; HEIGHT: 213px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5584196591637283618" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrY3l1EF-LjnBUH2PI0F7Vn71dpJM9Plft25uptCxdqhdF3wVjaTqblE0UwRVlKlhKzkkxR2cjmIJ3pYQ7yzQyywQWxpYBBG0C4zDIn8LMVjYLHMHTmAkVmIwRIWk8cb2cY91e9LKEP12U/s400/image003.png" /></span></a><span style="font-size:85%;"><br />3.加入FlashRemoting與Binder兩種組件至元件庫,然後各拖拉一個到圖層之中。<br /></span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSONVyPpl0wkho6cyBBJWfWSVhJ7mmhQG7V9w-kobyD8-XmDAUmPIaYKG5l633EgbIkJOO7-rUNxylOGHPfG4DuQRByEkuN6tyRQAqEptwnvxtexEA3xyMWCW4o6FPdfN0WA-IOftA_2fl/s1600/image005.png"><span style="font-size:85%;"><img style="WIDTH: 400px; HEIGHT: 213px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5584196590729666066" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSONVyPpl0wkho6cyBBJWfWSVhJ7mmhQG7V9w-kobyD8-XmDAUmPIaYKG5l633EgbIkJOO7-rUNxylOGHPfG4DuQRByEkuN6tyRQAqEptwnvxtexEA3xyMWCW4o6FPdfN0WA-IOftA_2fl/s400/image005.png" /></span></a><span style="font-size:85%;"><br />4.在組件檢測器中設置參數,將FlashRemoting的controlPath值設為~/HelloWorld.ascx,Binder的bindName值設為firstValue,bindProperty值設為myFirst.text 。<br /></span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOQi7-mQytHqCZqUncSF3pmsuKV3SnxWSsuHrtg8QcY7rXG5KpeFWEpQQD8WBF1FYYADmp5vz5EbY6d7Khtzit-tggUY7WtpIcD24-aVqRjCppm8W_DHB2X8g9TVLfp6HUhtFzB7TQBx4Z/s1600/image007.png"><span style="font-size:85%;"><img style="WIDTH: 249px; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5584196595227946002" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOQi7-mQytHqCZqUncSF3pmsuKV3SnxWSsuHrtg8QcY7rXG5KpeFWEpQQD8WBF1FYYADmp5vz5EbY6d7Khtzit-tggUY7WtpIcD24-aVqRjCppm8W_DHB2X8g9TVLfp6HUhtFzB7TQBx4Z/s400/image007.png" /></span></a><span style="font-size:85%;"><br />5.最後測試影片就可以看到從網站傳進來的Hello World啦!<br /></span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVAnRnoih0qEDBE0fJta8E7l1VX83if13SElAGtd9Yr-aiH_M2MCtrwo5DQTMfX36TuHhb-vh3J4t7-rzzu5KxN0hQd5wJC5lilPJ1bWRU_fyTf2cFF8o8-IpDi3Tx78jlUbGNK0Yyjath/s1600/image009.png"><span style="font-size:85%;"><img style="WIDTH: 400px; HEIGHT: 324px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5584196598345970930" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVAnRnoih0qEDBE0fJta8E7l1VX83if13SElAGtd9Yr-aiH_M2MCtrwo5DQTMfX36TuHhb-vh3J4t7-rzzu5KxN0hQd5wJC5lilPJ1bWRU_fyTf2cFF8o8-IpDi3Tx78jlUbGNK0Yyjath/s400/image009.png" /></span></a><span style="font-size:85%;"><br />怎麼樣?是不是很簡單呢!<br /><br />當然這個只是向前端丟出資料的例子,接下來還有一篇將說明如何讓資料回傳與溝通資料的方法。<br /><br />這技術主要依靠開放原始碼的FluorineFx元件達成AMF的資料傳輸,屬於一種Remoting技術所以沒有太多傳遞物件的限制,詳細請自行參考它的官方網站,這裡我只是運用將其包裝進原本ASP.NET Web Form就設計好的架構框架而已。<br /><br />ASP.NET的UserControl與Flash的元件圖層有著幾乎完全相似的父子階層架構,UserControl中可以依照設計放置其它UserControl,元件圖層內也可以放置其它元件使用,如果是由了解這關係的開發人員與設計師搭配相信一定能很快的使用這項技術迅速開發出活潑快速的Flash互動網站。 </span>JurioLihttp://www.blogger.com/profile/05017404652191063718noreply@blogger.com0