مطالب
آموزش (jQuery) جی کوئری 1#
با سلام خدمت دوستان عزیز
تصمیم گرفتم در طی چندین پست در حد توانم به آموزش jQuery بپردازم. (مطالب نوشته شده برداشت ازادی از کتاب jQuery in action است)

جی کوئری (jQuery) چیست؟
jQuery یک کتابخانه بسیار مفید برای جاوا اسکریپت است. بسیار ساده و کارآمد است و مشکل جاوا اسکریپت را برای تطابق با مرورگرهای اینترنتی مختلف برطرف نموده است؛ یادگیریjQuery بسیار آسان است. در جی کوئری کد جاوا اسکریپت از فایل HTML جدا شده و بنابراین کنترل کدھا و بھینه‌سازی آنھا بسیار ساده‌تر خواھد شد. توابعی برای کار با AJAX فراھم نموده و در این زمینه نیز کار را بسیار ساده کرده است. در جی کوئری می‌توان از خصوصیت فراخوانی زنجیره‌ای متدھا استفاده نمود و این باعث می‌شود چندین کد فقط در یک سطر قرار گیرد و در نتیجه کد بسیار مختصر گردد. در مقایسه با سایر ابزارهایی که تاکید عمده‌ای بروی تکنیک‌های هوشمند جاوا اسکریپت دارند، هدف جی کوئری تغییر تفکر سازندگان وب سایت‌ها، به ایجاد صفحه‌هایی با کارکرد بالا می‌باشد. به جای صرف زمان برای مقابله با پیچیدگی‌های جاوا اسکریپت پیشرفته، طراحان می‌توانند با استفاده از زمان و دانش خود در زمینه‌ی CSS، HTML، XHTML و جاوا اسکریپت‌های ساده، عناصر صفحه را مستقیما دستکاری کنند و از همین طریق تغییرهای گشترده و سریعی انجام دهند.

نکته: برای استفاده از جی کوئری باید HTML و CSS و جاوا اسکریپت آشنایی داشته باشید.

چگونه از جی کوئری استفاده کنیم؟
برای استفاده از جی کوئری باید ابتدا فایل آن را از سایت آن دانلود کرده و در پروژه خود استفاده نمایید. البته روش‌های دیگری برای استفاده از این فایل وجود دارد که در آینده بیشتر با آن آشنا خواهیم شد. برای استفاده از این فایل در پروژه باید به شکل زیر آن را به صفحه HTML خود معرفی کنیم.
<html>
   <head>
       <script type="text/javascript" src="jquery-1.9.1.min.js"></script>
   </head>
   <body>
   </body>
</html>
سپس بعد از معرفی خط فوق در قسمت head صفحه باید کد‌های خود را در یک تگ script بنویسیم.

کوتاه کردن کد: هر زمان شما خواسته باشید کارکرد یک صفحه وب را پویا‌تر کنید، در اکثر مواقع به ناچار این کار از طریق عناصری بروی صفحه انجام داده اید که با توجه به انتخاب شدن آنها، صفحه کارکردی خاص خواهد داشت. مثلا در جاوا اسکریپت اگر بخواهیم عنصری را که در یک radioGroup انتخاب شده است را برگردانیم باید کد‌های زیر را بنویسیم:
var checkedValue;
var elements = document.getElementByTagName ('input');
for (var n = 0; n < elements.length; n++) {
       if (elements[n].type == 'radio' && elements[n].name == 'myRadioGroup' && elements[n].checked) {
               checkedValue = elements[n].value;
       }
}
اما اگر بخواهیم همین کد را با جی کوئری بنویسیم:
var checkedValue = $ ('[name="myRadioGroup"]:checked').val();
ممکن است مثال بالا کمی گنگ باشد نگران نباشید در آینده با این دستورات بیشتر آشنا خواهیم شد.
قدرت اصلی جی کوئری برگفته از انتخاب‌کننده‌ها (Selector) هاست، انتخاب‌کننده ، یک عبارت است که دسترسی به عنصری خاص بر روی صفحه را موجب می‌شود؛ انتخاب‌کننده این امکان را فراهم می‌سازد تا به سادگی عنصر مورد نظر را مشخص و به آن دسترسی پیدا کنیم که در مثال فوق، عنصر مورد نظر ما گزینه انتخاب شده از myRadioGroup بود.
Unobtrusive JavaScript: اگر پیش از پیدایش CSS در کار ایجاد صفحه‌های اینترنتی بوده‌اید حتما مشکلات و مشقات آن دوران را به خاطر می‌آورید. در آن زمان برای فرمت‌دهی به اجزای مختلف صفحه ، به ناچار علائم فرمت‌دهی را به همراه دستورات خود اجزا، در صفحه‌های HTML استفاده می‌کردیم. اکنون بسیار بعید به نظر می‌رسد کسی ترجیح دهد فرمت‌دهی اجزا را به همراه دستورهای HTML آن انجام دهد. اگر چه هنوز دستوری مانند زیر بسیار عادی به نظر می‌آید:
<button type="button" onclick="document.getElementById('xyz').style.color='red';">
        Click Me
</button>
نکته ای که در مثال فوق حائز اهمیت است، این است که خصوصیات ظاهری دکمه ایجاد شده از قبیل فونت و عنوان دکمه، از طریق تگ <font> و یا پارامترهای قابل استفاده در خود دستور دکمه تعیین نشده است، بلکه CSS وظیفه تعیین آنها را دارد. اما اگرچه در این مثال فرمت‌دهی و دستور خود دکمه از یکدیگر جدا شده‌اند؛ شاهد ترکیب این دکمه با رفتار آن هستیم. در جی کوئری می‌توانیم رفتار را از اجزا به آسانی جدا کنیم.

مجموعه عناصر در جی کوئری:

زمانی که CSS به عنوان یک تکنولوژی به منظور جداسازی طراحی از ساختار به دنیای صفحه‌های اینترنتی معرفی شد، می‌بایست راهی برای اشاره به اجزای صفحات از طرف فایل CSS نیز معرفی می‌شد. این امر از طریق انتخاب‌کننده‌ها (Selector) صورت پذیرفت.

برای مثال انتخاب‌کننده زیر، به تمام عناصر <a> اشاره دارد که در یک عنصر <p> قرار گرفته‌اند:

p a
جی کوئری نیز از چنین انتخاب‌کننده‌هایی استفاده می‌کند، الته نه تنها از انتخاب‌کننده‌هایی که هم اکنون در CSS موجود می‌باشند، بلکه برخی از انتخاب‌کننده‌هایی که هنوز در تمام مرورگرها پشتیبانی نمی‌شوند.
برای انتخاب مجموعه‌ای از عناصر از یکی از دو Syntax زیر استفاده می‌کنیم.
$(Selector)
یا
jQuery(Selector)
ممکن است در ابتدا ()$ کمی نا معمول به نظر آید، اما اکثر کسانی که با جی کوئری کار می‌کنند از اختصار و کوتاهی این ساختار استفاده می‌کنند.
مثال زیر نمونه‌ای دیگر است که در آن مجموعه‌ای از تمام لینک‌هایی که درون تگ <p> قرار دارند را انتخاب می‌کند:
$("p a")
تابع ()$ که در حقیقت نام خلاصه‌ای برای ()jQuery می‌باشد، نوع خروجی مخصوصی دارد که شامل یک آرایه از اشیایی می‌شود که انتخاب‌کننده آن را برگزیده است. این نوع خروجی این مزیت را دارد که شمار زیادی متد از پیش تعریف شده را داراست که به سادگی قابل اعمال می‌باشند.
در اصطلاح برنامه نویسی به چنین توابعی که گروهی از عناصر را جمع می‌کنند، Wrapper می‌گویند زیرا تمام عناصر مطلوب را تحت یک شی بسته‌بندی می‌کند. در جی‌کوئری به آنها Wrapped Set یا jQuery Wrapper می‌گویند و به متدهایی که قابل اعمال بروی اینها به نام jQuery Wrapper Methodes شناخته می‌شوند.
در مثال زیر می‌خواهیم تمام عناصر <div> در صورتی که دارای کلاس notLongForThisWorldباشند را مخفی (با فید شدن) کنیم.

$("div.notLongForThisWorld").fadeOut();
یکی از مزیت‌های اکثر متدهای قابل اجرا بروی مجموعه عناصر انتخاب شده آن است که خروجی خود آنها مجموعه‌ای دیگر است. به این معنا که خروجی این متد، آماده اعمال یک متد دیگر است.
فرض کنید در مثال بالا بخواهیم پس از مخفی کردن هر <div> بخواهیم یک کلاس به نام removedبه آن بیافزاییم. به این منظور می‌توان کدی مانند زیر نوشت:
$("div.notLongForThisWorld").fadeOut().addClass("removed");
این زنجیره متدها می‌توانند به هرتعداد ادامه پیدا کند.

چند نمونه  انتخاب کننده:

نتیجه
  انتخاب کننده
 تمام <p>‌های زوج را انتخاب می‌کند

$('p:even')
 سطر اول هر جدول را انتخاب می‌کند

$("tr:nth-child(1)");
 <div>هایی که مستقیما در <body> تعریف شده باشند را انتخاب می‌کند.

$("body > div");
 لینک هایی که به یک فایل pdf اشاره دارند را انتخاب می‌کند.

$("a[href$=pdf]");
 تمام <div> هایی که مستقیما در <body> معرفی شده اند و دارای لینک می‌باشند را انتخاب می‌کند.

$("body > div:has(a)")
   

ادامه مطالب در پست‌های بعدی تشریح خواهد شد.


جهت مطالعه بیشتر می‌توانید از این منابع ^  و  ^  و  ^  و  ^  و  ^ استفاده کنید.
موفق و موید باشید
نظرات مطالب
شروع به کار با EF Core 1.0 - قسمت 7 - بررسی رابطه‌ی One-to-Many
در جهت تکمیل بحث بارگذاری اطلاعات وابسته: اضافه شدن Lazy Loading به نگارش 2.1

برخلاف نگارش‌های پیشین EF، اینبار Lazy loading به صورت پیش‌فرض فعال نیست که در بسیاری از موارد یک مزیت مهم، در جهت بهبود کارآیی برنامه به حساب می‌آید؛ چون پیشتر مدام می‌بایستی توسط ابزارهای profiler، برنامه را بررسی می‌کردیم تا از وجود مشکلی به نام select n+1 مطلع می‌شدیم (lazy loading اشتباه، در جائی که نیازی به آن نبوده و رفت و برگشت بیش از اندازه‌ا‌ی را به بانک اطلاعاتی سبب شده‌است).
برای فعالسازی lazy loading در EF Core 2.1 (اگر واقعا به آن نیاز دارید البته) دو روش وجود دارد:
الف) فعالسازی Lazy loading توسط Proxyها
در این حالت ابتدا نیاز است بسته‌ی نیوگت Microsoft.EntityFrameworkCore.Proxies را نصب کنید. سپس در متد OnConfiguring مربوط به Context برنامه، متد UseLazyLoadingProxies را فراخوانی نمائید:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseLazyLoadingProxies()
        .UseSqlServer(myConnectionString);
و یا اینکار در فایل آغازین برنامه نیز میسر است:
    .AddDbContext<BloggingContext>(
        b => b.UseLazyLoadingProxies()
              .UseSqlServer(myConnectionString));
اکنون EF Core 2.1 خواص راهبری (navigation properties) را که قابل بازنویسی باشند (همان مباحث AOP و تشکیل پروکسی‌ها)، lazy load می‌کند.
این خواص نیز حتما باید به صورت virtual معرفی شوند تا قابلیت بازنویسی را داشته باشند؛ مانند:
public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public virtual Blog Blog { get; set; }
}
در این مثال با فعال بودن lazy loading، به محض لمس خاصیت Blog، اطلاعات مرتبط با آن از بانک اطلاعاتی واکشی خواهند شد و نه پیش از آن مانند eager loading که تمام اطلاعات وابسته‌ی به یک موجودیت را نیز واکشی می‌کند.
هرچند این قابلیت بارگذاری اطلاعات وابسته در آینده، جذاب به نظر می‌رسد اما در عمل در حین رندر یک گرید و یا بکارگیری حلقه‌ها، چون سبب رفت و برگشت بیش از اندازه‌ای به بانک اطلاعاتی خواهد شد، باید با دقت مورد استفاده قرار گیرد و اساسا استفاده‌ی از آن در برنامه‌های وب توصیه نمی‌شود (با بررسی‌های پروژه‌های بسیاری مشخص شده‌است که این قابلیت ضررش بیشتر از نفعش است).


ب) فعالسازی Lazy loading بدون استفاده از Proxyها
در این حالت نیازی به نصب بسته‌ی AOP جدید تشکیل پروکسی‌ها نیست. در اینجا در کلاس موجودیت خود باید سرویس ILazyLoader را تزریق کنید:
public class Blog
{
    private ICollection<Post> _posts;
public Blog()
    {
    }
private Blog(ILazyLoader lazyLoader)
    {
        LazyLoader = lazyLoader;
    }
private ILazyLoader LazyLoader { get; set; }
public int Id { get; set; }
    public string Name { get; set; }
public ICollection<Post> Posts
    {
        get => LazyLoader?.Load(this, ref _posts);
        set => _posts = value;
    }
}
public class Post
{
    private Blog _blog;
public Post()
    {
    }
private Post(ILazyLoader lazyLoader)
    {
        LazyLoader = lazyLoader;
    }
private ILazyLoader LazyLoader { get; set; }
public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
public Blog Blog
    {
        get => LazyLoader?.Load(this, ref _blog);
        set => _blog = value;
    }
}
در این روش نیازی به virtual معرفی کردن خواص راهبری نیست. اما در این حالت به علت استفاده‌ی از سرویس ILazyLoader، نیاز خواهید داشت تا بسته‌ی نیوگت Microsoft.EntityFrameworkCore.Abstractions را نیز نصب کنید.
مطالب
بازسازی کد: جایگزینی متغیر موقتی با پرس و جو (Replace temp with query)
زمانیکه متغیری برای نگهداری موقت نتیجه‌ی یک expression تعریف شده‌است، بهتر است expression مربوطه به متدی انتقال پیدا کرده و تمامی استفاده‌ها از متغیر موقتی با فراخوانی متد ایجاد شده جایگزین شوند. 
مشکل اصلی در ارتباط با متغیرهای محلی، ترویج ایجاد متدهای بلند توسط آنها است. مشخص است که این متغیرها در بدنه متد خود قابل استفاده هستند و تنها راه اشتراک مقدار آنها طولانی‌تر شدن متد است. اما زمانیکه این متغیرها با متد پرس و جوی مرتبط با آن جایگزین شوند، این مقدار توسط دیگر متدهای کلاس قابل دسترسی خواهد بود. این کار ایجاد متدهایی با اندازه مناسب را آسان‌تر می‌کند. 
این بازسازی کد بیشتر اوقات در کنار بازسازی استخراج متد استفاده می‌شود؛ به طوری که قبل از انجام استخراج متد، ابتدا تکلیف متغیرهای محلی مشخص می‌شود. یک نوع از متغیرهای محلی که نیاز به بررسی و تغییر خواهند داشت این دسته از متغیرهای محلی هستند.

مراحل انجام این بازسازی کد  

  • متغیر موقتی ای را که تنها یک بار مقداردهی شده است، پیدا کنید (در صورتیکه متغیر چندین بار مقداردهی شده باشد، باید بازسازی جداسازی متغیرهای موقتی را اعمال نمایید).
  • متغیر را به readonly تغییر دهید.
  • کد را کامپایل نمایید تا اطمینان حاصل کنید متغیر تنها یک بار مقداردهی شده‌است.
  • Expression سمت راست مقداردهی متغیر را به متد، منتقل نمایید. دو نکته در مورد متد تازه ایجاد شده:  
    • این متد را به صورت private تعریف نمایید. در صورتی در آینده مصرف دیگری برای آن پیدا کردید می‌توانید سطح دسترسی آن‌را آزادتر نمایید. 
    • اطمینان حاصل نمایید متد مورد نظر، شیء یا خصوصیتی را ویرایش نمی‌کند. در صورتیکه این کار را انجام می‌دهد، باید بخش ویرایش آن را از بخش پرس و جوی آن جدا نمایید (Separate query from modifier). 
  • کد را مجددا کامپایل نمایید.  
  • تمامی استفاده‌های متغیر را با فراخوانی متد ایجاد شده، تغییر دهید. 
مثال: تکه کد زیر را در نظر بگیرید  
public class OrderItem 
{ 
    private double quantity; 
    private double itemPrice; 
    public double CalculateTotal() 
    { 
        double basePrice = quantity * itemPrice; 

        if (basePrice > 1000) 
        { 
            return basePrice * 0.95; 
        } 
        else 
        { 
            return basePrice * 0.98; 
        } 
    } 
}

در این کلاس متدی برای محاسبه قیمت نهایی یک آیتم سفارش ایجاد شده‌است. با دقت در کد می‌توان تشخیص داد که متغیر basePrice یک متغیر محلی موقتی است. این تکه کد را می‌توان به صورت زیر بازسازی کرد   
public class OrderItem 
{ 
    private double quantity; 
    private double itemPrice; 
    public double CalculateTotal() 
    { 
        if (BasePrice() > 1000) 
        { 
            return BasePrice() * 0.95; 
        } 
        else 
        { 
            return BasePrice() * 0.98; 
        } 
    } 
    private double BasePrice() 
    { 
        return quantity * itemPrice; 
    } 
}
کد حاصل از بازسازی انجام شده، شامل یک متد به نام BasePrice است که مقدار قیمت پایه را بر می‌گرداند. این متد را به صورت private تعریف کردیم. اما می‌توان در صورت نیاز به override کردن آن در کلاس‌های مشتق شده‌ی احتمالی، سطح دستری آن را به مقدار مناسبی تغییر داد.  به نظر شما چه بازسازی کد دیگری را می‌توان بر روی متد CalculateTotal انجام داد؟ 

آیا این بازسازی کد تاثیر منفی بر کارآیی خواهد داشت؟ 

پاسخ سخت گیرانه به این پرسش بلی است. اما با وجود پردازنده‌های قوی حال حاضر و بهینه سازی‌های فراوانی که کامپایلرها در زمینه‌ی inlining انجام می‌دهند، این بازسازی کد تاثیر منفی شدیدی را بر روی کارایی نخواهد داشت. حتی با وجود تاثیر جزیی در کارآیی نرم افزار، تاثیر مثبتی که این بازسازی در خوانایی و قدرت مدیریت و توسعه دارد، این بازسازی را یکی از انتخاب‌های جدی اعمال بر روی کدهای مشکل دار می‌کند.  
مطالب
نصب dotnet core framework روی اوبونتو 16.04
مایکروسافت در چند سال اخیر و به خصوص بعد از روی کار آمدن ساتیا نادلا،  رویکرد خاصی را به مباحث Cross Platform پیدا کرد، تا جایی که dotnet core شکل گرفت. این فناوری جدید به شما این امکان را میدهد تا دات نت فریمورک را بر روی سیستم عامل‌های دیگری چون لینوکس و مک نصب کنید. در سایت اختصاصی این فناوری،  نحوه نصب آن بر روی توزیع‌های مختلف سیستم عامل  لینوکس،  توضیحاتی داده شده است و یکی از این آموزش‌ها مربوط به پرچم دار توزیع‌های لینوکس و به خصوص خانواده دبیان یعنی اوبونتو است. در این راهنما، تنها نسخه خاصی از اوبونتو یعنی نسخه 14.04 آن مدنظر می‌باشد ولی آخرین نسخه اوبونتو 16.04 است که در اینباره توضیحی داده نشده است و با نصب آن به مشکل بر می‌خورد. در این مقاله میخواهیم نصب dotnet core را بر روی آخرین نسخه این سیستم عامل، بررسی کنیم.

با توجه به ابتدای آموزش، کدهای زیر را در ترمینال وارد میکنیم:
sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list'

sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893

sudo apt-get update
اولین خط از لینوکس، مخزنی را که فایل‌های مربوط به دات نت، در آن قرار دارند، در لینوکس ثبت می‌کند. دستور sh وظیفه‌ی اجرای اسکریپت را بر عهده دارد که میتوانید یک فایل اسکریپت را به آن معرفی کنید. ولی اگر با سوپیچ c به کار رود، می‌توانید خود دستور ارسالی را به آن معرفی کنید. اجرای این اسکریپت منجر به معرفی مخازن دات نت می‌شود که میتواند برای نصب و به روزرسانی آن به کار رود. در ساختار فایل‌های خانواده‌ی دبیان، فایلی به نام Sources.list وجود دارد که شامل آدرس مخازن رسمی اوبونتو جهت دریافت نرم افزاری‌ها آن می‌شود. ولی اگر قرار باشد مخازنی جدای از مخازن رسمی معرفی گردند، باید داخل دایرکتوری sources.list.d قرار گیرند و با نامی مشخص و با همان فرمت مشخص، ذخیره گردند.

در خط  دوم،  کلید اختصاصی این پکیج جهت اعتبارسنجی معرفی می‌گردد که در سایت جاری قبلا به آن پرداخته شده است. در خط آخر هم مخازن موجود را به روزرسانی می‌کنیم تا آماده استفاده شود.
در سایت مایکروسافت از شما خواسته می‌شود که کد زیر را وارد کنید:
sudo apt-get install dotnet-dev-1.0.0-preview1-002702
ولی بهتر است به جای آن از جدیدترین بسته استفاده کنید که باگ آن رفع شده است و علت باگ قبلا به آن پرداخته شده است. پس کد زیر را به جای کد بالا وارد می‌کنیم:
sudo apt-get install dotnet-dev-1.0.0-preview2-003096
چه بسته قبلی و چه جدید را نصب کنید، به خطای زیر برخورد خواهید کرد:
The following packages have unmet dependencies:
 dotnet-dev-1.0.0-preview1-002702 : Depends: dotnet-sharedframework-microsoft.netcore.app-1.0.0-rc2-3002702 but it is not going to be installed
E: Unable to correct problems, you have held broken packages.
که برای حل آن، باید ابتدا بسته‌ی وابسته نصب گردد و سپس دستور بالا دوباره اجرا شود. برای دریافت این وابستگی، به این لینک مراجعه کنید و فایل مربوطه را که با پسوند deb است، دریافت کنید. بعد از آن باید فایل دریافتی را نصب نمایید که برای نصب این نوع بسته‌ها از دستور زیر استفاده می‌کنیم:
sudo dpkg -i libicu52_52.1-3ubuntu0.4_amd64.deb
بعد از نصب موفقیت آمیز این بسته، دستورات زیر را اجرا میکنیم تا بسته dotnet core نصب شود:
sudo apt-get install dotnet-sharedframework-microsoft.netcore.app-1.0.0-rc2-3002702
sudo apt-get install dotnet-dev-1.0.0-preview2-003096
بعد از اتمام نصب، دستور زیر را جهت اطمینان از صحت نصب وارد کنید، تا نسخه نصب شده جاری به شما نمایش داده شود:
dotnet --version
خروجی:
1.0.0-preview2-003096
البته ممکن است خروجی دفعه اول به خاطر پیام‌های خوش آمدگویی، خطوط بیشتری را داشته باشد، ولی برای دفعات آینده همین یک خط است.
مطالب
ساخت Nuget Manager شخصی
یکی از راحت‌ترین راه‌های افزودن پکیج‌های برنامه نویسی به پروژه‌های دات نت، از طریق Nuget میباشد. این ابزار به قدری راحت است که من تصمیم گرفتم پکیج‌های تیممان را از طریق این سیستم دریافت کنیم. مزیت آن هم این است که بچه‌های تیم همیشه به پکیج‌ها دسترسی راحت‌تری دارند و هم اینکه در آینده به روز رسانی ساده‌تری خواهند داشت. با توجه به اینکه سایت اصلی تنها پکیج‌های عمومی را پشتیبانی می‌کند و چیزی تحت عنوان پکیج‌های شخصی ندارد، پس باید خودمان این سرویس را راه اندازی کنیم. برای راه اندازی این سیستم می‌توان آن را بر روی سیستم شخصی قرار داد و یا اینکه به صورت اینترنتی بر روی یک سرور به آن دسترسی داشته باشیم. در این مقاله این دو روش را بررسی میکنم:

پی نوشت: برای داشتن نیوگت شخصی سایت‌های نظیر Nuget Server و Myget ( به همراه پشتیبانی از مخازن npm و Bower ) هم این سرویس را ارائه میکنند. ولی باید هزینه‌ی آن را پرداخت کنید. البته سایت GemFury مخازن رایگان مختلفی چون Nuget را نیز پشتیبانی می‌کند.


نصب بر روی یک سیستم شخصی یا لوکال


در اولین قدم، شما باید یک دایرکتوری را در سیستم خود درست کنید تا پکیج‌های خود را داخل آن قرار دهید. پنجره‌ی Package manager Settings را باز کنید و در آن گزینه‌ی Package Sources را انتخاب کنید. سپس در کادر باز شده،  بر روی دکمه‌ی افزودن، در بالا کلیک کنید تا در پایین کادر، از شما نام محل توزیع بسته و آدرس آن را بپرسد:


بعد از ورود اطلاعات، بر روی دکمه‌ی Update کلیک کنید. از این پس این دایرکتوری، منبع پکیج‌های شماست و برای دریافت پکیج‌ها از این آدرس می‌توانید از طریق منوی کشویی موجود در کنسول، پکیج جدید خودتان را انتخاب کنید:


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

مرحله‌ی بعدی این است که از طریق ابزار خط فرمان نیوگت نسخه 3.3 پکیج‌هایتان را به دایرکتوری مربوطه انتقال دهید. نحوه‌ی صدا زدن این دستور به شکل زیر است:
nuget init e:\nuget\ e:\nuget\test
این دستور تمام پکیج‌هایی را که شما در مسیر اولی قرار داده‌اید، به داخل دایرکتوری test منتقل می‌کند. ولی اگر قصد دارید که فقط یکی از پکیج‌ها را به این دایرکتوری انتقال دهید از دستور زیر استفاده کنید:
nuget add GMap.Net.1.0.1.nupkg -source e:\nuget\test
اینبار با کلمه‌ی رزرو شده‌ی add و بعد از آن نام پکیچ، دایرکتوری منبع را به آن معرفی می‌کنیم.


ساخت منبع راه دور (اینترنت)


شما با استفاده از ویژوال استودیو و انجام چند عمل ساده می‌توانید پکیج‌های خودتان را مدیریت کنید. برای شروع، یک پروژه‌ی تحت وب خام (Empty) را ایجاد کنید و در کنسول Nuget دستور زیر را وارد کنید:
Install-Package NuGet.Server
شما با نصب این بسته و وابستگی‌هایش، به راحتی یک سیستم مدیریت بسته را دارید. ممکن است مدتی برای نصب طول بکشد و در نهایت از شما بخواهد که فایل web.config را رونویسی کند که شما اجازه‌ی آن را صادر خواهید کرد. بعد از اتمام نصب، فایل web.config را گشوده و در خط زیر، خصوصیت Value را به یک دایرکتوری که دلخواه که مدنظر شماست تغییر دهید. این آدرس دهی می‌تواند به صورت مطلق باشد، یا آدرس مجازی آن را وارد کنید؛ یا اگر هم خالی بگذارید به طور پیش فرض دایرکتوری Packages را در نظر میگیرد:
<appSettings>
    <!-- Set the value here to specify your custom packages folder. -->
    <add key="packagesPath" value="×\Packages" />
</appSettings>
حال فایل‌های دایرکتوری محلی خود را به دایرکتوری Packages انتقال دهید و سپس سایت را بر روی IIS، هاست نمایید. از این پس منبع شما به صورت آنلاین مانند آدرس زیر در دسترس خواهد بود.
(هر محلی که نصب کنید طبق الگوی مسیریابی، آدرس nuget را در انتها وارد کنید)
Dotnettips.info/nuget

در صورتی که قصد دارید مستقیما بسته‌ای را به سمت سرور push کنید، از یک رمز عبور قدرتمند که آن را می‌توانید در web.config، بخش apiKey وارد نمایید، استفاده کنید. اگر هم نمی‌خواهید، می‌توانید در تگ RequiredApiKey در خصوصیت Value، مقدار false را وارد نمایید.
برای اینکار می‌توانید از دستور زیر استفاده کنید:
nuget push GMap.Net.1.0.1.nupkg -source http://Dotenettips.info/nuget (ApiKey)
البته اگر قبل از دستور بالا، دستور زیر را وار کنید، دیگر نیازی نیست تا برای دستورات بعدی تا مدتی ApiKey را وارد نمایید.
nuget setapikey -source https://www.dntips.ir/Nuget (ApiKey)
مطالب
آشنایی با CLR: قسمت بیست و سوم
در قسمت قبل یاد گرفتیم که اگر یک ناشر، باگی را در یک اسمبلی برطرف کند، باید مدیر سیستم با تغییر فایل پیکربندی، نسخه‌ی جدید اسمبلی را به CLR معرفی کند. ولی اگر ناشر بخواهد این اسمبلی را در اختیار همه‌ی کاربرانش قرار دهد و به همه‌ی کاربران بگوید که باید فایل را تغییر دهید، این روش آن چنان راحت و مناسب نیست. به همین دلیل ناشر باید یک فایل تعیین سیاست داشته باشد، تا این کار راحت صورت بگیرد.
بیایید فرض کنیم که شما، ناشر این اسمبلی جدید با رفع باگ‌های اسمبلی قبلی هستید. موقعیکه شما یک اسمبلی جدید را توزیع می‌کنید، به همراه آن فایل پیکربندی جدیدی را تشکیل داده و ارسال می‌کنید. این فایل پیکربندی جدید دقیقا شبیه به همان فایل پیکربندی است که با آن آشنا شدیم، منتها همنام اسمبلی مورد نظر می‌باشد؛ مثل dotnettips.config برای dotnettips.dll.
<configuration>
     <runtime>
        <assemblyBinding xmlns="urn:schemas­microsoft­com:asm.v1">
           <dependentAssembly>
                <assemblyIdentity name="SomeClassLibrary"  publicKeyToken="32ab4ba45e0a69a1" culture="neutral"/>
                <bindingRedirect   oldVersion="1.0.0.0" newVersion="2.0.0.0" />
                <codeBase version="2.0.0.0"  href="http://www.Wintellect.com/SomeClassLibrary.dll"/>
             </dependentAssembly>
        </assemblyBinding>
     </runtime>
  </configuration>
در واقع این فایل، تنها یک تعیین سیاست برای این اسمبلی است و تنها از همین المان‌هایی که در بالا می‌بینید، می‌شود استفاده کرد و المان‌هایی غیر از آن‌ها مثل Probing یا publisher policy در اینجا قابل استفاده نیست. خطوط بالا به CLR میگویند، هر موقع به نسخه‌ی یک این اسمبلی ارجاعی را داشتی، از نسخه‌ی 2 آن استفاده کن. برای ساخت فایل بالا می‌توانید از طریق دستور زیر نیز اقدام کنید:
AL.exe /out:Policy.1.0.SomeClassLibrary.dll
          /version:1.0.0.0          
/keyfile:MyCompany.snk         
/linkresource:SomeClassLibrary.config
تشریح دستور بالا به شکل زیر است:

سوئییچ out باعث ساخت فایل PE با نام مشخص شده می‌باشد که تنها شامل یک manifest می‌شود و شامل 5 بخش می‌شود:
  بخش اول شامل عبارت policy است تا بگویید که این اسمبلی شامل یک فایل اطلاعاتی درباره سیاست‌های تعیین شده است.  بخش دوم و سوم مربوط به ورژن اسمبلی است که به ترتیب major و minor آن مشخص می‌شوند و این سیاست‌ها فقط روی این نسخه‌ها اتفاق می‌افتد. ادامه شماره نسخه‌ها چون revision number و ... اهمیتی ندارد و فقط همان دو مقدار اول شرط اصلی هستند. بخش چهارم هم شامل نام اسمبلی مربوطه می‌شود و بخش پنجم هم پسوند اسمبلی است.
سوئیچ version تنها مشخص کننده ورژن فایل پیکربندی است و هیچ ارتباطی با ورژن خود اسمبلی ندارد. این ورژن به این دلیل است که مثلا امروز ناشر دوست دارد که CLR به جای اسمبلی 1.0.0، نسخه‌ی 2.0.0 آن مورد استفاده قرار بگیرد. ولی در آینده تصمیم می‌گیرد از نسخه‌ی 1.0.0 به نسخه‌ی 2.5.0 هدایت شود و در اینجاست که بالاترین نسخه‌ی فایل پیکربندی مورد استفاده قرار می‌گیرد.

سوئیچ KeyFile بدیهی است که فایل سیاست‌های یک اسمبلی با نام قوی نیز باید با جفت کلید عمومی و خصوصی که برای خود اسمبلی مورد نظر استفاده می‌کنید، امضاء شود و بدین ترتیب CLR این اطمینان را کسب کند که واقعا این فایل پیکربندی متعلق به آن است.

سوئیچ linkresource هم میگوید که فایل پیکربندی قرار است جدای از اسمبلی باشد و ناشر باید این فایل را به همراه نسخه‌ی جدید اسمبلی ارسال و توزیع کند. شما نمی‌توانید با استفاده از سوئیچ EmbedResource فایل پیکربندی را داخل اسمبلی قرار دهید؛ چون CLR انتظار دارد این فایل جدا باشد. (در مورد این سوئیچ‌ها در قسمت شانزدهم توضیح داده‌ایم)

در صورتی که اسمبلی جدید ناشر، باگ‌های بیشتری به همراه داشته باشد، به طوریکه ادمین میخواهد فعلا این فایل سیاست‌های تعیین شده جدید را موقتا لغو کند، می‌تواند تگ زیر را در فایل پیکربندی اصلی به کار ببرد:
<publisherPolicy apply="no"/>
نحوه‌ی استفاده از این تگ را در قسمت قبلی دیده بودیم.

پایان فصل سوم و بخش اول
مطالب
معرفی ES 6
جاوا اسکریپت، پیاده سازی ECMA Script است (با تلفظ اکما اسکریپت) که به صورت مخفف به آن ES هم گفته می‌شود و ES 6، در حقیقت نگارش 6 این استاندارد است که به آن ECMA Script 2015 نیز می‌گویند (زمان نهایی شدن استاندارد آن سال 2015 است) و از زمان ارائه‌ی جاوا اسکریپت، بزرگترین تغییر و تحول آن نیز محسوب می‌گردد. با ES 6 مواردی مانند کلاس‌ها، برنامه نویسی تابعی (functional programming)، ماژول‌ها و غیره اضافه شده‌اند.



چرا باید ES 6 را آموخت؟

در طی 2 سال آینده، تمام فریم ورک‌های جدید جاوا اسکریپتی، از بوت استرپ 4 تا AngularJS 2 تا Aurelia و غیره، همگی به ES 6 کوچ خواهند کرد (و این اتفاق هم اکنون در حال رخ دادن است). بنابراین به زودی بدون فراگیری و تسلط بر ES 6، در حوزه‌ی وب، «بی‌سواد» محسوب خواهید شد و فراگیری آن یک «باید» است.


وضعیت پشتیبانی از ES 6 در مرورگرهای مختلف

برای مشاهده‌ی پیشرفت‌های مرورگرهای کنونی در زمینه‌ی پشتیبانی از ES 6‌، می‌توان به صفحه‌ی ES 6 compatibility table مراجعه کرد.


برای نمونه در حال حاضر، فایرفاکس بهترین پشتیبانی از ES 6 را ارائه می‌دهد (با پیاده سازی 85 درصد از قابلیت‌ها) و بعد از آن مرورگر جدید مایکروسافت قرار دارد.
وضعیت IE 10,11 در این بین تغییری نخواهند کرد؛ زیرا پشتیبانی رسمی از تمام آن‌ها به زودی خاتمه می‌یابد (در سه شنبه، ۲۲ دی ۱۳۹۴).
در همین صفحه، در ابتدای چارت، ستون current browser نیز قرار دارد. این ستون، وضعیت مرورگر جاری شما را از لحاظ درصد پیاده سازی قابلیت‌های ES 6 نمایش می‌دهد.


اهمیت دریافت آخرین نگارش‌های مرورگرها

با توجه به ES 6 compatibility table، اکثر مرورگرها در نسخه‌های شبانه و همچنین آزمایشی آن‌ها، به مرور در حال افزودن قابلیت‌های باقیمانده‌ی ES 6 هستند. بنابراین اگر با فایرفاکس کار می‌کنید، نیاز است Firefox nightly builds را نصب کنید. اگر از مرورگرهای مایکروسافت استفاده می‌کنید، آخرین نگارش MS Edge بهترین پشتیبانی از ES 6 را ارائه می‌دهد و اگر از کروم استفاده می‌کنید، نگارش‌‌های بتا و Dev آن را می‌توانید دریافت کنید.

علاوه بر این‌ها، نگارش‌های فعلی این مرورگرها نیز دارای امکانات آزمایشی هستند که می‌توان آن‌ها را به صورت دستی فعال کرد. برای مثال در مرورگر کروم، به آدرس chrome://flags مراجعه کنید و در صفحه‌ی باز شده، کلمه‌ی JavaScript را جستجو کنید. در اینجا نیاز است گزینه‌ی «Enable Experimental JavaScript» را فعال کنید (بر روی لینک enable ذیل آن کلیک نمائید).


به این ترتیب قادر خواهید بود آخرین افزونه‌های ES 6 را در developer tools console آن اجرا کنید.

چنین تنظیمی به MS Edge نیز اضافه شده‌است. پس از اجرای آن، به آدرس about:flags مراجعه کنید:


در اینجا نیز می‌توانید گزینه‌ی «Enable experimental JavaScript features» را انتخاب کنید.


معرفی traceur-compiler

هرچند قابلیت‌های فعلی آخرین نگارش‌های مرورگرها برای اجرای بسیاری از امکانات ES 6 کفایت می‌کنند، اما اگر علاقمند به اجرای تمامی آن‌ها هستید، می‌توان از traceur-compiler گوگل نیز کمک گرفت (با تلفظ تریسر). این کامپایلر، قابلیت‌های جدید ES 6 را تبدیل به نگارش‌های فعلی قابل درک برای مرورگرهای قدیمی‌تر می‌کند. به این ترتیب امکان اجرای آزمایشات مرتبط با ES 6 را خواهید یافت.
روش استفاده‌ی از آن هم به صورت ذیل است:
<script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
<script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script>
<script type="module">
// ES 6
</script>
ابتدا نیاز است دو اسکریپت اصلی تریسر را به صفحه الحاق کنید. پس از آن نوع تگ اسکریپت را به module تنظیم کنید. در این بین قادر خواهید بود به تمامی امکانات ES 6 در مرورگر فعلی خود دسترسی داشته باشید.
مطالب
آشنایی با CLR: قسمت پنجم
اجرای کدهای اسمبلی

همانطور که قبلا ذکر کردیم یک اسمبلی شامل کدهای IL و متادیتا هاست. IL یک زبان غیر وابسته به معماری سی پی یو است که مایکروسافت پس از مشاوره‌های زیاد از طریق نویسندگان کامپایلر و زبان‌های آکادمی و تجاری آن را ایجاد کرده است. IL یک زبان کاملا سطح بالا نسبت به زبان‌های ماشین سی پی یو است. IL می‌تواند به انواع اشیاء دسترسی داشته و آن‌ها را دستکاری نماید و شامل دستورالعمل هایی برای ایجاد و آماده سازی اشیاست. صدا زدن متدهای مجازی بر روی اشیاء و دستکاری المان‌های یک آرایه به صورت مستقیم، از جمله کارهایی است که انجام می‌دهد. همچنین شامل دستوراتی برای صدور و کنترل استثناء هاست . شما می‌توانید IL را به عنوان یک زبان ماشین شیء گرایی تصور کنید.
معمولا برنامه نویس‌ها در یک زبان سطح بالا چون سی شارپ به نوشتن می‌پردازند و کمپایلر کد IL آن‌ها را ایجاد می‌کند و این کد IL می‌تواند به صورت اسمبلی نوشته شود. به همین علت مایکروسافت ابزار ILASM.exe و برای دی اسمبل کردن ILDASM.exe را ارائه کرده است.
این را همیشه به یاد داشته باشید که زبان‌های سطح بالا تنها به زیر قسمتی از قابلیت‌های CLR دسترسی دارند؛ ولی در IL Assembly توسعه دهنده به تمامی قابلیت‌های CLR دسترسی دارد. این انتخاب شما در زبان برنامه نویسی است که می‌خواهید تا چه حد به قابلیت‌های CLR دسترسی داشته باشید. البته یکپارچه بودن محیط در CLR باعث پیوند خوردن کد‌ها به یکدیگر می‌شود. برای مثال می‌توانید قسمتی از یک پروژه که کار خواندن و نوشتن عملیات را به عهده دارد بر دوش #C قرار دهید و محاسبات امور مالی را به APL بسپارید.

برای اجرا شدن کدهای IL، ابتدا CLR باید بر اساس معماری سی پی یو کد ماشین را به دست آورد که وظیفه‌ی تبدیل آن بر عهده Jit یا Just in Time است . شکل زیر نحوه انجام این کار را انجام می‌دهد:



قبل از اجرای متد Main، ابتدا CLR به دنبال ارجاعاتی می‌گردد که در این متد استفاده شده است تا یک ساختار داده داخلی، برای ارجاعات این متد در حافظه تشکیل شود. در شکل بالا یک ارجاع وجود دارد و آن هم شیء کنسول است. این ساختار داده داخلی شامل یک مدخل ورودی (آدرس آغاز در حافظه) به ازای هر متد تعریف شده در نوع کنسول است. هر مدخل ورودی شامل آدرسی است که متدها در آنجا پیاده سازی شده‌اند. موقعیکه این آماده سازی انجام می‌گیرد، آن‌ها را به سمت یک تابع مستند نشده در خود CLR به نام Jit Compiler ارسال می‌کند.
موقعیکه کنسول اولین متدش مثلا WriteLine را فراخوانی می‌کند، کامپایلر جیت صدا زده می‌شود. تابع کامپایلر جیت مسئولیت تبدیل کدهای IL را به کدهای بومی آن پلتفرم، به عهده دارد. از آنجایی که عمل کامپایل در همان لحظه یا در جا اتفاق می‌افتد (Just in time)، عموم این کامپایر را Jitter یا Jit Compiler می‌نامند.

موقعیکه صدا زدن آن متد به سمت jit انجام شد، جیت متوجه می‌شود که چه متدی درخواست شده و نحوه‌ی تعریف آن متد به چه صورتی است. جیت هم در متادیتای یک اسمبلی به جست و جو پرداخته و کدهای IL آن متد را دریافت می‌کند. سپس کدها را تایید و عملیات کامپایل به سمت کدهای بومی را آغاز می‌کند. در ادامه این کدهای بومی را در قطعه‌ای از حافظه ذخیره می‌کند. سپس جیت به جایی بر می‌گردد که CLR از آنجا جیت را وارد کار کرده؛ یعنی مدخل ورودی متد writeline و سپس آدرس آن قطعه حافظه را که شامل کد بومی است، بجای آن قطعه که به کد IL اشاره می‌کند، جابجا می‌کند و کد بومی شده را اجرا و نهایتا به محدوده‌ی main باز می‌گردد.
در شکل زیر مجددا همان متد صدا زده شده است. ولی از آنجا که قبلا کد کامپایل شده را به دست آوردیم، از همان استفاده می‌کنیم و دیگر تابع جیت را صدا نمی‌زنیم.


  توجه داشته باشید، در متدهای چند ریختی که شکل‌های متفاوتی از پارامترها را دارند، هر کدام کمپایل جداگانه‌ای صورت می‌گیرد. یعنی برای متدهای زیر جیت برای هر کدام جداگانه فراخوانی می‌شود.
WriteLine("Hello");
WriteLine();

در مقاله‌ی آینده عملکرد جیت را بیشتر مورد بررسی قرار می‌دهیم و در مورد دیباگ کردن و به نظرم برتری CLR  را نسبت به زبان‌های مدیریت نشده، بررسی می‌کنیم.

مطالب
آشنایی با WPF قسمت اول : ساختار سلسله مراتبی


عناصر رابط کاربری WPF با یکدیگر یک رابطه‌ی سلسله مراتبی دارند. به این رابطه، درخت منطقی یا Logical Tree می‌گویند که به توصیف ارتباط اجزای رابط کاربری می‌پردازد. نوع دیگری از درخت نیز وجود دارد که به آن درخت بصری یا Visual Tree می‌گویند. این درخت شامل عناصری است که باعث نمایش کنترل پدر می‌شوند و کنترل پدر بدون آن‌ها هیچ ظاهر نمایشی ندارد. به عنوان مثال شما یک دکمه را در نظر بگیرید. این دکمه شامل عناصری چون Border,Block Text,Content Presenter می‌شود تا بتواند به عنوان یک دکمه نمایش یابد و بدون وجود این عناصر، کنترل دکمه هیچ ظاهری ندارد و در واقع با رندر شدن کنترل‌های فرزندان، دکمه معنا پیدا می‌کند. به تصویر بالا دقت کنید که به خوبی مرز بین درخت منطقی و درخت بصری را نمایش می‌دهد. شکل سلسله مراتبی بالا از طریق کد زیر به دست آمده است:
 
<Window>
    <Grid>
        <Label Content="Label" />
        <Button Content="Button" />
    </Grid>
</Window>
درخت بصری می‌تواند به ما کمک کند تا بتوانیم بر روی عناصر تشکیل دهنده، یک کنترل قدرت عمل داشته باشیم و آن‌ها را مورد تغییر قرار دهیم.


Dependency Properties

خاصیت‌های وابستگی همان خاصیت‌ها یا property هایی هستند در ویندوزفرم با آن‌ها سر و کله می‌زدید ولی در اینجا تفاوت‌هایی با پراپرتی‌های قبلی وجود دارد که باعث ایجاد مزایای زیادی شده است.

اول اینکه
بر خلاف پراپرتی‌های ویندوز فرم که در خود فیلدهای تعیین شده همان کنترل ذخیره می‌شدند، در این روش کلید (نام پراپرتی) و مقدار آن داخل یک شیء دیکشنری قرار می‌گیرند که از شیء DependencyObject ارث بری شده است و این شیء والد یک متد با نام GetValue برای دریافت مقادیر دارد. مزیت این روش این است که بیخود و بی‌جهت مانند روش قبلی، ما فیلدهایی را تعریف نمی‌کنیم که شاید به نصف بیشتر آن‌ها، حتی نیازی نداریم. در این حالت تنها فیلدهایی از حافظه را دریافت و ذخیره می‌کنیم که واقعا به آن‌ها نیاز داریم. فیلدها یا مقادیر پیش فرض موقع ایجاد شیء در آن ذخیره می‌شوند.

دومین مزیت این روش خاصیت ارث بری مقادیر از عناصر بالاتر درخت منطقی است. موقعی که از طرف شما برای فرزندان این عنصر مقداری تعیین نشده باشد، سیستم به  سمت گره‌ها یا عناصر بالا یا والد حرکت می‌کند و اولین عنصری را که مقدارش تنظیم شده باشد، برای فرزندان در نظر می‌گیرد. به این استراتژی یافتن یک مقدار، استراتژی Resolution می‌گویند.

سومین مزیت آن وجود یک سیستم اعلان یا گزارش آنی است. در صورتی که شما یک تابع callback را برای یک پراپرتی ست نمایید، با تغییر این پراپرتی تابع معرفی شده صدا زده خواهد شد.

Value Resolution Strategy
همانطور که در بالا اشاره کردیم دریافت مقادیر یک کنترل از طریق یک استراتژی به اسم Resolution انجام می‌شود که طبق تصویر زیر از بالا به پایین بررسی می‌شود. در هر کدام از مراحل زیر اگر مقداری یافت شد، همان مقدار را انتخاب می‌کند. از متد SetValue هم برای درج مقدار استفاده می‌شود. برای مثال در مرحله‌ی سوم بررسی می‌شود که آیا کاربر برای کنترل مورد نظر مقداری را تنظیم کرده است یا خیر؛ اگر آری، پس از آن استفاده می‌کند و اگر پاسخ خیر بود، بررسی می‌کند آیا style برای آن موجود است که مقداری برایش تنظیم شده باشد یا خیر و الی آخر...

جادوی پشت صحنه

مقادیر پراپرتی‌ها در کلاسی استاتیک به اسم Dependency Property ذخیره می‌شوند که این ذخیره در حالت نام و مقدار است و مقدار آن شامل callback و مقدار پیش فرض است. شکل زیر نتیجه‌ی شکل دقیق‌تری را نسبت به قبلی در هنگام پیمایش درخت منطقی به سمت بالا، نشان می‌دهد.

نحوه‌ی تعریف یک خاصیت وابسته که باید به صورت ایستا تعریف شود به صورت زیر است و برای دریافت و درج مقدار جدید از یک پراپرتی معمولی کمک می‌گیریم:

// Dependency Property
public static readonly DependencyProperty CurrentTimeProperty = 
     DependencyProperty.Register( "CurrentTime", typeof(DateTime),
     typeof(MyClockControl), new FrameworkPropertyMetadata(DateTime.Now));
 
// .NET Property wrapper
public DateTime CurrentTime
{
    get { return (DateTime)GetValue(CurrentTimeProperty); }
    set { SetValue(CurrentTimeProperty, value); }
}
یک قانون در WPF وجود دارد و آن اینست که نام خاصیت‌های وابسته را با کلمه Property به پایان ببرید مثل CurrentTimeProperty.
در مورد خاصیت‌های وابسته و کدنویسی آن ها در مطالب آینده بیشتر بحث خواهیم کرد.

مطالب
ایجاد سرویس چندلایه‎ی WCF با Entity Framework در قالب پروژه - 9
یک Windows Form جدید ایجاد کنید و نام آن را frmAddEditNews بگذارید. 
برابر با شکل ویژگی‌های IsDeleted، tblCategory و tblNewsId را برابر با None کنید و tblCategoryId را از نوع Combobox انتخاب کنید. سپس با فشار فلش کنار tblNews گزینه‌ی Details را انتخاب کنید.

روی tblNews کلیک کرده آن‌را بکشید و روی فرم رها کنید. آن‌گاه ظاهر فرم و چیدمان کنترل‌ها را تنظیم کنید و دو دکمه ذخیره و لغو برابر با شکل در فرم ایجاد کنید:

کد روی‌داد دو دکمه را این‌گونه بنویسید:

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
        }

در پایین فرم روی tblNewsBindingSource کلیک کنید و از قسمت Properties ویژگی Modifiers آن‌را برابر با Public کنید. 

روی Combobox کلیک کنید، سپس ویژگی DataBinding -> Text آن‌را خالی کنید. سپس روی فلش بالای Combobox دسته خبر کلیک کنید و تنظیمات آن‌را مانند شکل زیر انجام دهید.

برای پرشدن آن کد زیر را در روی‌داد Load فرم این‌گونه بنویسید:

        private void frmAddEditNews_Load(object sender, EventArgs e)
        {
            MyNewsService.MyNewsServiceClient MyNews = new MyNewsService.MyNewsServiceClient();
            tblCategoryIdComboBox.DataSource = MyNews.GetAllCategory();
        }

به فرم اصلی بازگردید و برای روی‌داد دکمه‌ی ویرایش چنین بنویسید:

        private void btnEdit_Click(object sender, EventArgs e)
        {
            if (tblNewsDataGridView.CurrentRow == null)
            {
                MessageBox.Show("سطری برای ویرایش انتخاب کنید");
            }
            else
            {
                //tblNews news = tblNewsDataGridView.CurrentRow.DataBoundItem as tblNews;
                tblNews news  = MyNews.GetNews(Convert.ToInt32(tblNewsDataGridView.CurrentRow.Cells["tblNewsId"].Value));
                frmAddEditNews frmAdd = new frmAddEditNews();
                frmAdd.tblNewsBindingSource.DataSource = news;
                if (frmAdd.ShowDialog() == DialogResult.OK)
                {
                    MyNews.EditNews(news);
                    tblNewsBindingSource.DataSource = MyNews.GetAllNews().Select(p => new { p.tblNewsId, p.tblCategory.CatName, p.Title, p.Description, RegDate = MiladiToShamsi(p.RegDate) });
                }
            }
        }

در صورتی که متد GetAllNews را به صورت ساده به ویژگی DataSource دیتاگرید نسبت داده بودیم می‌توانستید از کد زیر برای مقداردهی به متغیر news بهره ببریم. ولی در حال حاضر این خط کد پیغام خطا می‌دهد. البته راه‌های دیگری برای حل این مشکل وجود دارد که در این درس قصد پرداختن به آن‌را ندارم.

tblNews news = tblNewsDataGridView.CurrentRow.DataBoundItem as tblNews;

کد مربوط به روی‌داد دکمه‌ی افزودن و حذف را نیز به صورت زیر بنویسید:

        private void btnAdd_Click(object sender, EventArgs e)
        {
            tblNews news = new tblNews();
            frmAddEditNews frmAdd = new frmAddEditNews();
            frmAdd.tblNewsBindingSource.DataSource = news;
            if (frmAdd.ShowDialog() == DialogResult.OK)
            {
                MyNews.AddNews(news);
                tblNewsBindingSource.DataSource = MyNews.GetAllNews().Select(p => new { p.tblNewsId, p.tblCategory.CatName, p.Title, p.Description, RegDate = MiladiToShamsi(p.RegDate) });
            }
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("آیا با حذف این سطر اطمینان دارید؟","هشدار",MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
            {
                MyNews.DeleteNews(Convert.ToInt32(tblNewsDataGridView.CurrentRow.Cells["tblNewsId"].Value));
                tblNewsBindingSource.DataSource = MyNews.GetAllNews().Select(p => new { p.tblNewsId, p.tblCategory.CatName, p.Title, p.Description, RegDate = MiladiToShamsi(p.RegDate) });
            }
        }

برنامه را اجرا کنید. کار ما کم و بیش به پایان رسیده است. شما یک پروژه‌ی ویندوز ساده با استفاده از WCF ای که از Entity Framework برای اتصال به پایگاه داده بهره می‌برد؛ ایجاد کردید. WCF بسیار گسترده‌تر از این است و در این‌جا تنها به بخشی از آن پرداختیم. احتمالاً در صورت استقبال خوانندگان در آینده درباره‌ی تنظیمات ریز WCF برای امنیت، سرعت، محدودیت و استفاده در محیط‌های مختلف خواهم نوشت.

شاد و پیروز باشید.