۱۳۸۹ بهمن ۱۴, پنجشنبه

عوض کردن انیمیشن بارگذاری اولیه در سیلورلایت

تا حالا شده بخواهید آن انیمیشن بارگذاری اولیه برنامه سیلورلایتتون رو عوض کنید؟
انجام اینکار بسیار ساده است و بیشتر به یک طراح نیاز دارد تا برنامه نویس.

یک پروژه سیلورلایت ایجاد کنید و به پروژه وب آن یک فایل XAML اضافه کنید(من نام این فایل رو PreLoader گذاشتم).
! توجه کنید که برای طراحی لازم است مراجع PresentationCore و PresentationFramework و WindowsBase و System.Xml را در پروژه وبتان داشته باشید.
حالا هرچه که می خواهید هنگام بارگذاری نمایش داده شود را طراحی کنید و کنترلرهایی که نیاز به دانستن مقدار بارگذاری شده برنامه سیلورتان دارند را نام گذاری کنید.من فایل PreLoader ام را به شکل زیر ویرایش کردم:

 <Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="White">  
   <Grid VerticalAlignment="Center" Margin="20,0">  
     <Grid.RowDefinitions>  
       <RowDefinition Height="Auto" MinHeight="2"/>  
       <RowDefinition/>  
     </Grid.RowDefinitions>  
     <Border x:Name="progressBorder" BorderThickness="2" Height="25" Padding="2">  
       <Border.BorderBrush>  
         <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">  
           <LinearGradientBrush.RelativeTransform>  
             <RotateTransform CenterY="0.5" CenterX="0.5" Angle="270"/>  
           </LinearGradientBrush.RelativeTransform>  
           <GradientStop Color="#FF6F64F9" Offset="0"/>  
           <GradientStop Color="#FF1300FF" Offset="1"/>  
         </LinearGradientBrush>  
       </Border.BorderBrush>  
         <Rectangle x:Name="progressBar" Height="17" HorizontalAlignment="Left">  
           <Rectangle.Fill>  
             <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">  
               <LinearGradientBrush.RelativeTransform>  
                 <RotateTransform Angle="-90" CenterX="0.5" CenterY="0.5" />  
               </LinearGradientBrush.RelativeTransform>  
               <GradientStop Color="#FFCBD0FB" Offset="0"/>  
               <GradientStop Color="#FF383BFB" Offset="1"/>  
             </LinearGradientBrush>  
           </Rectangle.Fill>  
         </Rectangle>  
     </Border>  
     <Viewbox Grid.Row="1" Height="70">  
       <TextBlock x:Name="percentText" TextWrapping="Wrap" Foreground="#FF202DED" Text="0"/>  
     </Viewbox>  
   </Grid>  
 </Grid>  

اگر به پروژه وبتون دقت کرده باشید دو صفحه یکی html و یکی با پسوند aspx با نام AppName]TestPage] وجود دارد حالا صفحه ای که پسوند اون aspx هست رو باز کنید و پارامترهای زیر را به تگ object اضافه کنید:

 <param name="splashScreenSource" value="PreLoader.xaml" />  
 <param name="onSourceDownloadProgressChanged" value="onSilverAppDownloadProgressChanged" />  

در دو تگ فوق ما آدرس splash screen ای که می خواهیم نمایش داده شود را برابر PreLoader.xaml قرار دادیم (این آدرس برای شما می تواند متفاوت باشد) وسپس رویداد پیشرفت دانلود شدن برنامه سیلورمان(فایل xap) به کلاینت را هندل می کنیم بنابراین لازم است یک تابع با نام onSilverAppDownloadProgressChanged داشته باشیم و به وسیله ی آن با تغییر مقدار دانلود فایل xap آن را به PreLoader مان گزارش دهیم. برای این کار کمی جاوا اسکریپت نیاز داریم که می توانید آن را در یک فایل js قرار دهید و سپس به صفحه لینکش کنید یا آن را در تک script همین صفحه قرار دهید.
داخل تگ script تابع زیر را اضافه کنید:

     function onSilverAppDownloadProgressChanged(sender, args) {  
       var progressBorder = sender.findName("progressBorder");  
       var progressBar = sender.findName("progressBar");  
       var percentText = sender.findName("percentText");  
       progressBar.width = args.progress * progressBorder.actualWidth;  
       percentText.text = Math.round(args.progress * 100, 2) + "%";  
     }  

در ابتدای این تابع ما فقط چند عنصر را از داخل فایل xaml مان دریافت می کنیم(در اینجا پارامتر sender در اصل همان عنصر ریشه Grid در همان فایل xaml مان می باشد) تا بتونیم مقدار پیشرویی دانلود(با تغییر دادن width عنصر progressBar و اختصاص دادن درصد پیشروی دانلود به percentText) را نمایش دهیم.

برای مشاهده عملکرد PreLoader تان یک فایل حدودا" 30 مگی به پروژه سیلورتان اضافه کنید و سپس Build Action آن را برابر Content یا Resource قرار دهید(برای تغییر Build Action بر روی فایل راست کلیک و Prorperties را انتخاب کنید).

دانلود سورس برنامه.

موفق باشید.

۱۳۸۹ آبان ۵, چهارشنبه

نوشتن یک چت روم در سیلورلایت (مقدمه ای بر WCF Duplex Communication)

سلام خدمت دوستان گرامی


 در طول این آموزش ما یک چت روم ساده در سیلورلایت خواهیم ساخت که بستر ارتباطاتش WCF خواهد بود

 - Duplex Communication (ارتباط دو طرفه) :
 اغلب ارتباطات بین یک سرور و کلاینت با یک درخواست از طرف کلاینت آغاز و با پاسخ سرور به اتمام می رسد
این در حالی است که برخی از مواقع سرور می خواهد اطلاعاتی را به کلاینت(ها) ارسال کند که این می شود در خواستی از طرف سرور برای ارسال اطلاعات به کلاینت. و ارتباط دو طرفه یعنی زمانی که هم سرور و هم کلاینت هر دو بتوانند از یک دیگر درخواست و به یک دیگر پاسخ دهند.
اما ارتباط دو طرفه تحت پروتکل HTTP غیر ممکن است : زیرا پروتکل HTTP بر پایه یک در خواست از طرف کلاینت و سپس پاسخی از طرف سرور است بنابراین در این پروتکل اگر کلاینت درخواستی ندهد سرور نمی تواند پاسخی بدهد.


پس چگونه یک ارتباط دو طرفه تحت HTTP داشته باشیم؟


- Polling Duplex Binding در WCF :
 این نوع Binding در WCF معرفی شد تا بتواند یک ارتباط دو طرفه را شبیه سازی کند(البته پروتکل Polling Duplex مخصوص WCF نیست). نحوه ی کار این پروتکل اینگونه است که کلاینت مستمرا" درخواست هایی به سرور می فرستد(Poll) تا از موجود بودن یا نبودن اطلاعات جدید بر روی سرور برای خودش(کلاینت) آگاهی پیدا کند و اگر اطلاعات موجود بود با درخواست کلاینت آن اطلاعات توسط سرور به کلاینت ارسال می شوند.

مقدمه کافی است. برای نوشتن این برنامه شما باید موارد زیر را نصب کرده باشید:

MS Visual Studio 2010
VS Silverlight 4 Tools (دانلود)

- شروع کنیم؟!

VS را باز کنید بر روی New Project کلیک کنید و در پنجره باز شده در قسمت Installed Templates بر روی Silverlight کلیک کنید و در قسمت راست بر روی Silverlight Application کلیک و یک نام برای پروژه بنویسید(من گذاشتم SLSampleChat) و OK را بزنید سپس در قسمت Options پنجره New Silverlight Application که باز می شود Silverlight 4 را انتخاب و Enable WCF RIA Services را تیک بزنید و OK کنید.

وقتی برای اولین بار پروژه باز می شود تب مربوط به طراحی MainPage باز می شود(این همان صفحه اصلی ای هست که کاربر در مروگرش می بیند).
یک TextBlock (برای نمایش گفتگوها) و یک TextBox (برای تایپ متن) و یک دکمه (برای ارسال متن) به ترتیب با نام های txtLocalMessages و txtMessage و btnSend بر روی MainPage تان قرار دهید یا می توانید تگ Grid را به شکل زیر ویرایش کنید:

   <Grid x:Name="LayoutRoot" Background="White">  
     <Grid.ColumnDefinitions>  
       <ColumnDefinition Width="*" />  
       <ColumnDefinition Width="Auto" />  
     </Grid.ColumnDefinitions>  
     <Grid.RowDefinitions>  
       <RowDefinition Height="*" />  
       <RowDefinition Height="Auto" />  
     </Grid.RowDefinitions>  
     <TextBlock x:Name="txtLocalMessages" Grid.ColumnSpan="2" />  
     <TextBox x:Name="txtMessage" Grid.Row="1" />  
     <Button x:Name="btnSend" Grid.Column="1" Grid.Row="1" Content="Send" />  
   </Grid>  

 در Solution Explorer بر روی پروژه SLSampleChat.Web راست کلیک کرده و Add -> New Item را انتخاب کنید. در پنجره باز شده در سمت راست(Installed Templates) بر روی Silverlight کلیک کنید و در سمت چپ آیتم Silverlight-enabled WCF Service را انتخاب و نام آن را ChatService.svc بگذارید و بر روی دکمه Add کلیک کنید.
ChatService.svc را باز کنید و صفت زیر را بالای کلاس ChatService قرار دهید(زیر دو صفت دیگر):

 [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]  

صفت فوق تعیین کننده ی رفتار و چگونگی اجرای سرویسی (در اینجا ChatService) است که با آن مزین شده.
مقدار Single که به خصیصه InstanceContextMode اختصاص داده شده بیانگر این است که سرویس ما فقط یکبار ساخته می شود و کلاینت(ها) از آن استفاده می کنند.
و مقدار Multiple که به خصیصه ConcurrencyMode اختصاص داده شده باعث می شود سرویس ما MultiThreading (چند نخی) رو پشتیبانی کنه.

یک رابط (Interface) با نام IChatNotifies به پروژه SLSampleChat.Web اضافه کنید و آن را به شکل زیر ویرایش کنید:

   [ServiceContract]  
   public interface IChatNotifies  
   {  
     [OperationContract(IsOneWay = true)]  
     void OnMessage(string message);  
   }  

در ادامه شما خواهید دید که ما برای با خبر ساختن کلاینت ها از پیامهای دریافتی در سرور از رابط فوق استفاده خواهیم کرد و در اصل کلاس فوق نقش یک CallBack (همان Event های امروزی) را اجرا می کند.

به کلاس ChatService برگردید و صفت ServiceContract را به شکل زیر ویرایش کنید:

 [ServiceContract(Namespace = "", CallbackContract = typeof(IChatNotifies))]  

این باعث میشه سرویس ما رابطی که CallBack های ما را معرفی کرده بشناسد و در اصل قابلیت Duplex Communication (ارتباط دو طرفه) را به سرویس اضافه کند و کلاینت ها را هم قادر به گوش دادن به این CallBack ها می سازد.

سپس فیلد زیر را به سرویس تان اضافه کنید:

 private SynchronizedCollection<IChatNotifies> m_Clients = new SynchronizedCollection<IChatNotifies>();  

این فیلد کلاینت هایی که به سرور معرفی می شوند را نگهداری می کند.(از نوع SynchronizedCollection استفاده شده چون Thread Safe است و کد را پیچیده نمی کند)

اگر کلاینتی بخواهد پیامهایی که توسط کلاینت های دیگر به سرور ارسال می شوند را دریافت کند پس می بایست خود را به سرور معرفی کند. ما این کار را توسط متد زیر در سرویس انجام می دهیم:

     [OperationContract(IsOneWay = true)]  
     public void Subscribe()  
     {  
       var newClient = OperationContext.Current.GetCallbackChannel<IChatNotifies>();  
       m_Clients.Add(newClient);  
     }  

متد GetCallbackChannel  یک کانال (از نوع IChatNotifies) مربوط به کلاینتی که متد Subscribe را صدا زده بدست می آورد تا ما به وسیله ی آن اطلاعات را از سرور به کلاینت ارسال کنیم.

نهایتا برای ارسال پیام متد زیر را به سرویس تان اضافه کنید:

     [OperationContract(IsOneWay = true)]  
     public void SendMessage(string message)  
     {  
       foreach (var client in m_Clients)  
       {  
         client.OnMessage(message);  
       }  
     }  

متد فوق هم پیام دریافتی را مستقیما به تمام کلاینت ها ارسال می کند.

بر روی پروژه SLSampleChat.Web راست کلیک کرده و Add Reference را انتخاب کنید سپس در پنجره باز شده
روی تب Browse کلیک کنید و به آدرس
C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries\Server بروید (این آدرس می تواند در سیستم شما کمی متفاوت باشد) حالا فایل System.ServiceModel.PollingDuplex.dll را انتخاب کنید و بر روی OK کلیک کنید.
فایل پیکربندی Web.config را باز کنید و تگ system.serviceModel را به شکل زیر ویرایش کنید:

  <system.serviceModel>  
   <extensions>  
    <bindingExtensions>  
     <add name="pollingDuplex" type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement, System.ServiceModel.PollingDuplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />  
    </bindingExtensions>  
   </extensions>  
   <bindings>  
    <pollingDuplex>  
     <binding name="myPollingDuplex" duplexMode="MultipleMessagesPerPoll" inactivityTimeout="00:05:00" receiveTimeout="00:05:00" serverPollTimeout="00:05:00" />  
    </pollingDuplex>  
   </bindings>  
   <services>  
    <service name="SLSampleChat.Web.ChatService">  
     <endpoint address="" binding="pollingDuplex" bindingConfiguration="myPollingDuplex" contract="SLSampleChat.Web.ChatService" />  
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />  
    </service>  
   </services>  
   <behaviors>  
    <serviceBehaviors>  
     <behavior name="">  
      <serviceMetadata httpGetEnabled="true" />  
      <serviceDebug includeExceptionDetailInFaults="false" />  
     </behavior>  
    </serviceBehaviors>  
   </behaviors>  
   <serviceHostingEnvironment aspNetCompatibilityEnabled="true"  
    multipleSiteBindingsEnabled="true" />  
  </system.serviceModel>  

پیکربندی فوق در ابتدا Polling Duplex Binding رو تعریف می کند(چون این نوع Binding به صورت پیش فرض تعریف نشده است) سپس یک PollingDuplexBinding ایجاد و آن را به Binding سرویس مان (ChatService) اختصاص می دهد.
(Binding خصوصیات ارتباط بین سرور و کلاینت یک سرویس را مشخص می کند(از جمله نوع پروتکل استفاده شده برای ارتباط))

از منوی Build گزینه ی Build Solution را انتخاب کنید و پس از Build شدن (اگر در این قسمت به خطایی برخورد کردید یکی از مراحل فوق را اشتباه انجام داده اید و ابتدا باید آن خطا را برطرف کنید) بر روی پروژه ی SLSampleChat راست کلیک کرده و Add Service Reference را بزنید. در پنجره باز شده بر روی دکمه Discover کلیک کنید و سپس بر روی OK کلیک کنید.

به محیط طراحی MainPage بروید و با کلیک بر روی دکمه Send رویدا کلیک آن را هندل کنید.
در بالای کلاس MainPage فضای نام SLSampleChat.ServiceReference1 را using کنید و سپس فیلد زیر را به این کلاس اضافه کنید:

 private ChatServiceClient m_ServiceContext = new ChatServiceClient(new PollingDuplexHttpBinding(PollingDuplexMode.MultipleMessagesPerPoll), new EndpointAddress("../ChatService.svc"));

بوسیله ی این فیلد ما می توانیم سرویسی که در سرور ساخته ایم را صدا بزنیم.
سازنده کلاس MainPage را به شکل زیر ویرایش کنید:

     public MainPage()  
     {  
       InitializeComponent();  
       m_ServiceContext.OnMessageReceived += OnMessageReceived;  
       m_ServiceContext.SubscribeAsync();  
     }  

کد فوق رویداد دریافت پیام از سرور را هندل و کلاینت را به سرور معرفی می کند.
سپس متد زیر را به کلاس اضافه کنید:

     private void OnMessageReceived(object s, OnMessageReceivedEventArgs e)  
     {  
       var msg = e.Error == null ? e.message : e.Error.Message;  
       txtLocalMessages.Text += msg + "\r\n";  
     }  

کد بالا چک می کند اگر خطایی هنگام دریافت پیام رخ داده باشد آن را نمایش دهد و در غیر اینصورت پیام را نمایش می دهد.

و نهایتا در متد کلیک دکمه Send کد زیر را وارد کنید:

       if (!string.IsNullOrEmpty(txtMessage.Text))  
         m_ServiceContext.SendMessageAsync(txtMessage.Text);  

کد فوق هم در صورت خالی نبودن پیام آن را به سرور ارسال می کند تا سرور آن را به کلاینت ها ارسال کند.

چت ما ساخته شد! برای اجرا بر روی دکمه Debug کلیک کنید سپس آدرس صفحه باز شده در مرورگرتان را کپی کنید و در تب یا مرورگری دیگر به آن آدرس بروید و خودتان با خودتان چت کنید!

*هرگونه استفاده از این آموزش بدون ذکر منبع ممنوع می باشد.
-------------------------------------
دانلود سورس برنامه
------------------------------------------------
بیشترین منابع استفاده شده:
فیلم آموزشی در مورد Duplex Communication
کتاب SL Data & Services
و ...
------------------------------------------------------------------

موفق باشید