نمایش نتایج 1 تا 9 از 9

نام تاپیک: RIATasks: یک مثال ساده از CRUD در Silverlight-قسمت اول

  1. #1
    کاربر دائمی آواتار piroozman
    تاریخ عضویت
    مهر 1386
    محل زندگی
    تهران
    سن
    48
    پست
    217

    RIATasks: یک مثال ساده از CRUD در Silverlight

    قسمت اول:


    دلیل نوشتن این فایل آموزشی این بود که می دیدم دوستان(من الجمله خودم) در رابطه با موضوع این مقاله مشکل داشته و منبع مناسبی (حداقل فارسی) برای این موضوع پیدا نمی کنند. برخی دوستان مطمئناً وقت زیادی را برای آموزش Silverlight سپری کرده اند اما همه می دانیم که کتابهای آموزشی به طور مفصل و عملی این روش ها را آموزش نمی دهند (حداقل من ندیدم) و برای آموزش قدم به قدم آن نیز نیاز به زمان زیادی هست. پس ما یک میانبر برای شما ایجاد کرده ایم.
    در ضمن در این مقاله روش استفاده از View Model نیز آموزش داده شده است و من اعتقاد دارم که استفاده از این روش مقدار کد نویسی شما را تا حد زیادی کاهش می دهد (که احتمالا شما انتظار آن را نداشتید) (هر چند به نظر می رسد پیچیدگی برنامه زیاد می شود). ولی به بنده اعتماد کنید. اجازه دهید که شروع کنیم:


    در خصوص CRUDمطمئناً Silverlight متفاوت است زیرا آن با وب سایتی که آنرا راه اندازی کرده است در ارتباط است و از یک ارتباط ناهمگام استفاده می کند. بنابراین آموزش برنامه ای کاربردی از این دست می تواند کمی چالش برانگیز باشد.
    بنا براین من یک مثال از نوع end-to-end مطرح می کنم که اهداف زیر را شامل می شود:

    • Create, Read, Update, Delete رکورد ها از دیتابیس
    • پیاده سازی فرمهای مبتنی بر امنیت
    • پیاده سازی امنیت Granular (تنها کاربر User One می تواند ببیند، ویرایش کند و Task های خود را ایجاد کند).
    • پیاده سازی روش View Model

    شیوه View Model



    روش View Model به یک برنامه نویس اجازه می دهد برنامه ای را ایجاد کند که به طور مطلق به صورت UI ( User Interface) نباشد.
    برنامه نویسی که فقط View Model و Model ایجاد می کند با طراحی که تسلط کافی در برنامه نویسی ندارد قادر خواهند بود در تولید برنامه های Silverlight با یکدیگر همکاری کامل داشته باشند.
    برنامه کاربردی



    ابتدا نگاهی به برنامه بیاندازیم

    وقتی شما به برنامه را اجرا می کنید شما به صورت Logged Out به برنامه ورود پیدا خواهید کرد. شما می توانید با باز کردن کمبوباکس می توانید به عنوان User One یا User Two به برنامه ورود پیدا کنید.

    با کلیک کردن روی Add می توانید یک وظیفه جدید را ایجاد کنید.

    با کلیک بر روی Update وظیفه ذخیره خواهد شد.


    با انتخاب هر یک از Task ها مشخصات Task انتخاب شده به کاربر نمایش داده می شود و با کلیک بر روی دکمه Update تمامی تغییرات ذخیره می شوند و کلیک بر روی Delete منجر به حذف Taskانتخاب شده خواهد شد.
    در قسمت دوم در خصوص نحوه ایجاد برنامه کاربردی صحبت خواهیم کرد.
    اصل مقاله
    آخرین ویرایش به وسیله piroozman : چهارشنبه 15 خرداد 1392 در 12:14 عصر

  2. #2
    کاربر دائمی آواتار piroozman
    تاریخ عضویت
    مهر 1386
    محل زندگی
    تهران
    سن
    48
    پست
    217

    RIATasks: یک مثال ساده از CRUD در Silverlight

    قسمت دوم:
    ساخت برنامه

    شما برای ایجاد برنامه به نرم افزارهای زیر احتیاج دارید:


    1. Visual Studio 2010 یا بالاتر
    2. Expression Blend 4 یا بالاتر
    3. SQL Server2005 یا بالاتر


    تنظیمات مربوط به دیتابیس



    یک دیتابیس جدید تحت RIATasks ایجاد کنید.

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


    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id =
    OBJECT_ID(N"[dbo].[Tasks]") AND type in (N"U"))
    BEGIN
    CREATE TABLE [dbo].[Tasks](
    [TaskID] [int] IDENTITY(1,1) NOT NULL,
    [TaskName] [nvarchar](50) NOT NULL,
    [TaskDescription] [nvarchar](max) NOT NULL,
    [UserID] [int] NOT NULL,
    CONSTRAINT [PK_Tasks] PRIMARY KEY CLUSTERED
    (
    [TaskID] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE =
    OFF, IGNORE_DUP_KEY =
    OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    END
    GO
    IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id =
    OBJECT_ID(N"[dbo].[Tasks]") AND name
    = N"IX_Tasks_UserID")
    CREATE NONCLUSTERED INDEX [IX_Tasks_UserID] ON [dbo].[Tasks]
    (
    [UserID] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
    SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF,
    DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,
    ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    GO

    شما باید تنظیمات امنیتی (Security ) مربوط به SQL را انجام دهید تا در مراحل بعدی برای اتصال به پایگاه داده مشکلی نداشته باشید.
    ایجاد یک پروژه Web Application


    در VS2010 از منوی File بر روی گزینه New Project کلیک کنید.

    یک برنامه Silverlight Application ایجاد کنید

    مقادیر پیش فرض را پذیرفته و روی OK کلیک کنید.

    پروژه ایجاد خواهد شد.
    فعال سازی Form Authentication
    در اینجا نیاز هستش که برنامه تحت وب از حالت Form Authentication استفاده کند. وقتی کاربر Login می کند یک authentication ‘token’ رمزگذاری شده در Web Browser کاربر ایجاد می شود که حاوی UseID است.این token (نشانه) به وسیله برنامه Silverlight وقتی که Web service را ایجاد می کند فراخوانی می شود. متدهای web service (در ادامه آنها را ایجاد خواهیم کرد) token را جهت تضمین امنیت بررسی خواهند کرد.
    فایل Web.config را باز کنید

    <authentication mode="Forms"/> را به فایل اضافه کرده آنرا ذخیره کنید و سپس فایل را ببندید.
    ساخت صفحه Deafult

    یک Web Form با نام Default Page به پروژه RIATasks.Web اضافه کنید.

    فایل RIATasksTestPage.aspx را باز کنید و به Source view سوئیچ کنید.

    از ابتدای تگ <!DOCTYPE . . . تا انتهای صفحه هر چه که هست کپی کنید.

    و آنرا در Source فایل Default.aspx از ابتدای تگ <DOCTYPE . . . تا انتهای صفحه به جای تمامی کدهای موجود الصاق کنید.
    نیاز هست که تگ Div را که کنترل Silverlight در آن قرار دارد را به یک کنترل Panel تبدیل کنیم. کنترل Panel را می توان وقتی که کاربر در حالت logged in قرار ندارد به صورت hide در آورد.
    برای انجام اینکار تغییرات زیر را انجام دهید
    جایگزین کنید: <div id="silverlightControlHost">
    با: <asp:panel id="silverlightControlHost" ="server">
    جایگزین کنید: </div>
    با: </asp:panel>
    حالایک کنترل Drop-down به منظور ورود کاربر یا همان user log in درست در زیر تگ form اضافه کنید. در برنامه واقعی این کار باید در یک login form انجام شود.
    کد های زیر را زیر تگ form الصاق کنید.
    <asp:DropDownList ID="ddlUser" ="server" AutoPostBack="True" 
    onselectedindexchanged="ddlUser_SelectedIndexChang ed">
    <asp:ListItem Selected="True" Value="0">Logged Out</asp:ListItem>
    <asp:ListItem Value="1">User One</asp:ListItem>
    <asp:ListItem Value="2">User Two</asp:ListItem>
    </asp:DropDownList>

    فایل Default.aspx.cs را باز کنید و تمامی کدهای زیر را در آن قرار دهید:


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.Security;

    namespace RIATasks.Web
    {
    public partial class Default : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    if (!Page.IsPostBack)
    {
    LogOut();
    }
    }

    #region ddlUser_SelectedIndexChanged
    protected void ddlUser_SelectedIndexChanged
    (object sender, EventArgs e)
    {
    int intSelectedUser =
    Convert.ToInt32(ddlUser.SelectedValue);
    if (intSelectedUser > 0)
    {
    LogUserIntoSite
    (Convert.ToInt32(ddlUser.SelectedValue));
    }
    else
    {
    LogOut();
    }
    }
    #endregion

    #region LogUserIn
    private void LogUserIntoSite(int intUser)
    {
    // Log the user into the site
    FormsAuthenticationTicket ticket =
    new FormsAuthenticationTicket (1,
    intUser.ToString(),
    DateTime.Now,
    DateTime.Now.AddDays(30),
    false,
    "Role One",
    FormsAuthentication.FormsCookiePath);

    // Encrypt the ticket.
    string encTicket =
    FormsAuthentication.Encrypt(ticket);

    // Create the cookie.
    Response.Cookies.Add
    (new HttpCookie
    (FormsAuthentication.FormsCookieName, encTicket));

    // Show the Silverlight control
    silverlightControlHost.Visible = true;
    }
    #endregion

    #region LogOut
    protected void LogOut()
    {
    FormsAuthentication.SignOut();

    // Hide the Silverlight control
    silverlightControlHost.Visible = false;
    }
    #endregion
    }
    }


    روی فایل Default.aspx کلیک راست کرده و آنرا به عنوان Start Page تعیین کنید.
    برای اجرای برنامه می توانید از کلید F5 استفاده کنید. پروژه اجرا شده و در Web Browser باز می شود. شما می توانید محتویات drop down را به منظور log in شدن یک کاربر تغییر دهید.
    Web browser را ببنید.
    در قسمت سوم در خصوص نحوه ایجاد لایه Data صحبت خواهیم کرد.
    اصل مقاله
    آخرین ویرایش به وسیله piroozman : چهارشنبه 15 خرداد 1392 در 20:05 عصر

  3. #3
    کاربر دائمی آواتار piroozman
    تاریخ عضویت
    مهر 1386
    محل زندگی
    تهران
    سن
    48
    پست
    217

    RIATasks: یک مثال ساده از CRUD در Silverlight

    قسمت سوم:
    ایجاد Data Layer

    یک کلاس از نوع Linq to SQL به سایت RIATasks.Web تحت عنوان RIATasksDB.dbml اضافه کنید.
    نکته: شما می توانید از Entity Framework به جای Linq to SQL ( یا هر نوع تکنولوژی دیگری که به Data دسترسی دارد) استفاده کنید. دلیل انتخاب Linq to SQL در این پروژه سهولت ایجاد تنظیمات آن می باشد.


    روی لینک Server Explorer کلیک کنید.

    یک connection به دیتابیس RIATasks ایجاد کنید و جدول Tasks را با موس کشیده و در محیط Object Relational Designer رها کنید.

    Data layer تکمیل شد. فایل را ذخیره کرده و آنرا ببندید.

    ایجاد Web Service

    یک فایل از نوع Web service به پروژه RIATasks تحت عنوان Webservice.asmx اضافه کنید.
    فایل Webservice.asmx.cs را باز کنید و تمامی کدهای زیر را با کدهای موجود در آن جایگزین کنید:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Services;

    namespace RIATasks.Web
    {
    [WebService(Namespace = "http://OpenLightGroup.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class WebService : System.Web.Services.WebService
    {
    #region GetCurrentUserID
    private int GetCurrentUserID()
    {
    int intUserID = -1;
    if (HttpContext.Current.User.Identity.IsAuthenticated )
    {
    // Get the current user
    intUserID =
    Convert.ToInt32(HttpContext.Current.User.Identity. Name);
    }
    return intUserID;
    }
    #endregion

    // Web Methods

    #region GetTasks
    [WebMethod]
    public List<Task> GetTasks()
    {
    // Create a collection to hold the results
    List<Task> colResult = new List<Task>();

    RIATasksDBDataContext DB = new RIATasksDBDataContext();

    var colTasks = from Tasks in DB.Tasks
    where Tasks.UserID == GetCurrentUserID()
    select Tasks;

    // Loop thru the Tasks
    foreach (var item in colTasks)
    {
    // Create a Task
    Task tmpTask = new Task();

    // Set only the TaskID and the Name
    // We do this because Description could be
    // a large amount of data that will slow down
    // the application and we don"t need it now
    tmpTask.TaskID = item.TaskID;
    tmpTask.TaskName = item.TaskName;

    // Add to the final results
    colResult.Add(tmpTask);
    }

    return colResult;
    }
    #endregion

    #region GetTask
    [WebMethod]
    public Task GetTask(int TaskID)
    {
    RIATasksDBDataContext DB = new RIATasksDBDataContext();

    var result = (from Tasks in DB.Tasks
    where Tasks.TaskID == TaskID
    where Tasks.UserID == GetCurrentUserID()
    select Tasks).FirstOrDefault();

    return result;
    }
    #endregion

    #region DeleteTask
    [WebMethod]
    public string DeleteTask(int TaskID)
    {
    string strError = "";
    RIATasksDBDataContext DB = new RIATasksDBDataContext();

    try
    {
    var result = (from Tasks in DB.Tasks
    where Tasks.TaskID == TaskID
    where Tasks.UserID == GetCurrentUserID()
    select Tasks).FirstOrDefault();

    if (result != null)
    {
    DB.Tasks.DeleteOnSubmit(result);
    DB.SubmitChanges();
    }
    }
    catch (Exception ex)
    {
    strError = ex.Message;
    }

    return strError;
    }
    #endregion

    #region UpdateTask
    [WebMethod]
    public string UpdateTask(Task objTask)
    {
    string strError = "";
    RIATasksDBDataContext DB = new RIATasksDBDataContext();

    try
    {
    var result = (from Tasks in DB.Tasks
    where Tasks.TaskID == objTask.TaskID
    where Tasks.UserID == GetCurrentUserID()
    select Tasks).FirstOrDefault();

    if (result != null)
    {
    result.TaskDescription = objTask.TaskDescription;
    result.TaskName = objTask.TaskName;

    DB.SubmitChanges();
    }
    }
    catch (Exception ex)
    {
    strError = ex.Message;
    }

    return strError;
    }
    #endregion

    #region InsertTask
    [WebMethod]
    public Task InsertTask(Task objTask)
    {
    RIATasksDBDataContext DB = new RIATasksDBDataContext();

    try
    {
    Task InsertTask = new Task();

    InsertTask.TaskDescription = objTask.TaskDescription;
    InsertTask.TaskName = objTask.TaskName;
    InsertTask.UserID = GetCurrentUserID();

    DB.Tasks.InsertOnSubmit(InsertTask);
    DB.SubmitChanges();

    // Set the TaskID
    objTask.TaskID = InsertTask.TaskID;
    }
    catch (Exception ex)
    {
    // Log the error
    objTask.TaskID = -1;
    objTask.TaskDescription = ex.Message;
    }

    return objTask;
    }
    #endregion
    }
    }

    توجه کنید که web service متد GetCurrentUserID() را که از Convert.ToInt32(HttpContext.Current.User.Identity. Name) استفاده می کند، برای به دست آوردن کاربر جاری فراخوانی می کند.
    UserID کاربر جاری وقتی که به برنامه log in می کند مشخص می شود و یک authentication ‘token’ ایجاد می شود. Web browser کاربر ها این token را به ازای تمامی تقاضاها پاس می کنند. از جمله تقاضاهای وب سرویس که به واسطه برنامه Silverlight ایجاد می شوند.

    برای بررسی صحت تنظیمات می توانید روی Webservice.asmx کلیک راست کرده و آن را با انتخاب گزینه View in Browser در مروگر خود ببینید.

    وب متدها به شما نمایش داده خواهد شد.
    نکته: شما می توانید به جای asmx از WCF استفاده کنید. علت این انتخاب راحتی توسعه asmx می باشد.
    در قسمت چهارم به سراغ پروژه Silverlight خواهیم رفت.
    اصل مقاله
    آخرین ویرایش به وسیله piroozman : چهارشنبه 15 خرداد 1392 در 21:03 عصر

  4. #4
    کاربر دائمی آواتار piroozman
    تاریخ عضویت
    مهر 1386
    محل زندگی
    تهران
    سن
    48
    پست
    217

    RIATasks: یک مثال ساده از CRUD در Silverlight

    قسمت چهارم:
    پروژه Silverlight

    حالا بریم سراغ پروژه RIATasks در قسمت Silverlight. ابتدا نیاز هست که یک reference از پروژه Silverlight به web service ای که درست کردیم ایجاد کنیم.
    سپس باید یک Model برای فراخوانی وب سرویس ایجاد کنیم و همچنین یک کلاس پشتیبان ICommand ایجاد خواهیم کرد که به این اجازه رو می دهد که به آسانی رویدادها را در View Model بالا بیاوریم.

    ایجاد Web Service Reference

    در پروژه سیلورلایت روی گزینه References کلیک راست کنید و سپس Add Service Reference را انتخاب کنید.

    روی دکمه Discover کلیک کنید
    عبارت wsRIATasks را برای Namespace وارد کنید.
    روی دکمه OK کلیک کنید.
    ارتباط پروژه Silverlight با Website تکمیل شد. کدهایی که درمراحل بعدی ایجاد خواهیم کرد با استفاده از این Reference اقدام به فراخوانی web service ی که ایجاد کرده ایم خواهند کرد.

    اضافه کردن References
    یک Reference به Microsoft.VisualBasic و System.ServiceModelبه پروژه ایجاد کنید.
    کلاس پشتیبان ICommand

    یک پوشه جدید تحت عوان Classes به پروژه سیلورلایت اضافه کنید و روی آن کلیک راست کرده و گزینه New Item . . . را انتخاب کنید.

    کلاسی تحت عوان DelegateCommand.cs ایجاد کنید و کد های زیر را در این کلاس جدید جایگزین کنید.

    using System.Windows.Input;
    using System;

    namespace RIATasks
    {
    public class DelegateCommand : ICommand
    {
    Func<object, bool> canExecute;
    Action<object> executeAction;
    bool canExecuteCache;

    public DelegateCommand(
    Action<object> executeAction,
    Func<object, bool> canExecute)
    {
    this.executeAction = executeAction;
    this.canExecute = canExecute;
    }

    #region ICommand Members

    public bool CanExecute(object parameter)
    {
    bool temp = canExecute(parameter);

    if (canExecuteCache != temp)
    {
    canExecuteCache = temp;
    if (CanExecuteChanged != null)
    {
    CanExecuteChanged(this, new EventArgs());
    }
    }

    return canExecuteCache;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
    executeAction(parameter);
    }

    #endregion
    }
    }

    این کلاس به آسانی به ما اجازه می دهد تا از ICommand ها را استفاده کنیم.
    انشالله در قسمت بعدی می ریم به سراغ ساخت Model ها.
    اصل مقاله

  5. #5
    کاربر دائمی آواتار piroozman
    تاریخ عضویت
    مهر 1386
    محل زندگی
    تهران
    سن
    48
    پست
    217

    RIATasks: یک مثال ساده از CRUD در Silverlight

    قسمت پنجم:
    Model

    یک پوشه جدید با نام Models ایجاد کنید و یک کلاس با نام TasksModel.cs در آن قراردهید و کد های زیر را در آن جایگزین کنید.

    using Microsoft.VisualBasic;
    using System.Linq;
    using System;
    using System.Collections.Generic;
    using System.ServiceModel;
    using RIATasks.wsRIATasks;

    namespace RIATasks
    {
    public class TasksModel
    {
    #region GetTask
    public static void GetTask(int TaskID,
    EventHandler<GetTaskCompletedEventArgs> eh)
    {
    // Set up web service call
    WebServiceSoapClient WS =
    new WebServiceSoapClient();

    // Set the EndpointAddress
    WS.Endpoint.Address =
    new EndpointAddress(GetBaseAddress());

    WS.GetTaskCompleted += eh;
    WS.GetTaskAsync(TaskID);
    }
    #endregion

    #region GetTasks
    public static void GetTasks
    (EventHandler<GetTasksCompletedEventArgs> eh)
    {
    // Set up web service call
    WebServiceSoapClient WS =
    new WebServiceSoapClient();

    // Set the EndpointAddress
    WS.Endpoint.Address =
    new EndpointAddress(GetBaseAddress());

    WS.GetTasksCompleted += eh;
    WS.GetTasksAsync();
    }
    #endregion

    #region DeleteTask
    public static void DeleteTask(int TaskID,
    EventHandler<DeleteTaskCompletedEventArgs> eh)
    {
    // Set up web service call
    WebServiceSoapClient WS =
    new WebServiceSoapClient();

    // Set the EndpointAddress
    WS.Endpoint.Address =
    new EndpointAddress(GetBaseAddress());

    WS.DeleteTaskCompleted += eh;
    WS.DeleteTaskAsync(TaskID);
    }
    #endregion

    #region UpdateTask
    public static void UpdateTask(Task objTask,
    EventHandler<UpdateTaskCompletedEventArgs> eh)
    {
    // Set up web service call
    WebServiceSoapClient WS = new WebServiceSoapClient();

    // Set the EndpointAddress
    WS.Endpoint.Address =
    new EndpointAddress(GetBaseAddress());

    WS.UpdateTaskCompleted += eh;
    WS.UpdateTaskAsync(objTask);
    }
    #endregion

    #region InsertTask
    public static void InsertTask(Task objTask,
    EventHandler<InsertTaskCompletedEventArgs> eh)
    {
    // Set up web service call
    WebServiceSoapClient WS = new WebServiceSoapClient();

    // Set the EndpointAddress
    WS.Endpoint.Address = new EndpointAddress(GetBaseAddress());

    WS.InsertTaskCompleted += eh;
    WS.InsertTaskAsync(objTask);
    }
    #endregion

    // Utility

    #region GetBaseAddress
    private static Uri GetBaseAddress()
    {
    // Get the web address of the .xap that launched this application
    string strBaseWebAddress =
    App.Current.Host.Source.AbsoluteUri;
    // Find the position of the ClientBin directory
    int PositionOfClientBin =
    App.Current.Host.Source.AbsoluteUri.ToLower().Inde xOf(@"/clientbin");
    // Strip off everything after the ClientBin directory
    strBaseWebAddress =
    Strings.Left(strBaseWebAddress, PositionOfClientBin);
    // Create a URI
    Uri UriWebService =
    new Uri(String.Format(@"{0}/WebService.asmx",
    strBaseWebAddress));
    // Return the base address
    return UriWebService;
    }
    #endregion
    }
    }

    نکته: GetBaseAddress() متدی است که مشخص می کند که آیا کاربر xap. را راه اندازی کرده است ( Silverlight application در برگیرنده آن هست) و با استفاده از آن مشخص می شود که آیا WebService.asmx وجود دارد یا خیر؟ متدهای Web Service از این آدرس برای فراخوانی Web Service استفاده می کنند.
    در حال حاضر ما متدها را در Model ایجاد کرده ایم. این متدها با متدهای موجود در Web Service که پیش از این ایجاده شده بودند در ارتباطند.
    در قسمت ششم ساخت View Model را آموزش خواهیم داد.

  6. #6
    کاربر دائمی آواتار piroozman
    تاریخ عضویت
    مهر 1386
    محل زندگی
    تهران
    سن
    48
    پست
    217

    RIATasks: یک مثال ساده از CRUD در Silverlight

    قسمت ششم:
    View Model

    پوشه ای به نام ViewModels به پروژه ایجاد کرده و کلاسی تحت عنوان MainPageModel.cs به آن اضافه کنید. تمامی کدهای زیر را در آن جایگزین کنید:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows.Input;
    using System.Windows;
    using RIATasks.wsRIATasks;

    namespace RIATasks
    {
    public class MainPageModel : INotifyPropertyChanged
    {
    public MainPageModel()
    {
    // Set the command property
    GetTasksCommand = new DelegateCommand(GetTasks, CanGetTasks);
    GetTaskCommand = new DelegateCommand(GetTask, CanGetTask);
    DeleteTaskCommand = new DelegateCommand(DeleteTask, CanDeleteTask);
    UpdateTaskCommand = new DelegateCommand(UpdateTask, CanUpdateTask);
    AddNewTaskCommand = new DelegateCommand(AddNewTask, CanAddNewTask);

    // The following line prevents Expression Blend
    // from showing an error when in design mode
    if (!DesignerProperties.IsInDesignTool)
    {
    // Get the Tasks for the current user
    GetTasks();

    // Set Visibility
    HasCurrentTask = Visibility.Collapsed;
    AddVisibility = Visibility.Visible;
    UpdateVisibility = Visibility.Collapsed;
    DeleteVisibility = Visibility.Collapsed;
    }
    }



    // Utility

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
    if (PropertyChanged != null)
    {
    PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
    }
    #endregion
    }
    }

    این کد INotifyPropertyChanged را که توسط Properties استفاده می شود ( در مراحل بعدی ایجاد خواهند شد) پیاده سازی می کند. این عمل موجب می شود که هر گونه تغییر و به روزرسانی در Properties در View قابل مشاهده باشد.
    سازنده ()MainPageModel، بعضی از ICommand ها را که در مراحل بعدی به طور کامل تعریف خواهند شد، راه اندازی خواهد کرد. همچنین متد ()GetTasks را که موجب فراخوانی Model (که موجب فراخوانی web service خواهد شد) می شود را فراخوانی می کند و تمامی Task های کاربری را که به نرم افزار ورود پیدا کرده است را بازیابی می کند.
    نکته: شما خطوط قرمز مواجی را زیر خطوط این کد مشاهده خواهید کرد زیرا مجموعه property ها و command ها هنوز به طور کامل تعریف نشده اند.
    کدهای زیر را به به این کلاس اضافه کنید:

    // Properties

    #region CurrentTask
    private Task _CurrentTask = new Task();
    public Task CurrentTask
    {
    get { return _CurrentTask; }
    private set
    {
    if (CurrentTask == value)
    {
    return;
    }
    _CurrentTask = value;
    this.NotifyPropertyChanged("CurrentTask");
    }
    }
    #endregion

    #region AddVisibility
    private Visibility _AddVisibility = Visibility.Visible;
    public Visibility AddVisibility
    {
    get { return _AddVisibility; }
    private set
    {
    if (AddVisibility == value)
    {
    return;
    }
    _AddVisibility = value;
    this.NotifyPropertyChanged("AddVisibility");
    }
    }
    #endregion

    #region UpdateVisibility
    private Visibility _UpdateVisibility = Visibility.Visible;
    public Visibility UpdateVisibility
    {
    get { return _UpdateVisibility; }
    private set
    {
    if (UpdateVisibility == value)
    {
    return;
    }
    _UpdateVisibility = value;
    this.NotifyPropertyChanged("UpdateVisibility");
    }
    }
    #endregion

    #region DeleteVisibility
    private Visibility _DeleteVisibility = Visibility.Visible;
    public Visibility DeleteVisibility
    {
    get { return _DeleteVisibility; }
    private set
    {
    if (DeleteVisibility == value)
    {
    return;
    }
    _DeleteVisibility = value;
    this.NotifyPropertyChanged("DeleteVisibility");
    }
    }
    #endregion

    #region HasTasks
    private Visibility _HasTasks = Visibility.Collapsed;
    public Visibility HasTasks
    {
    get { return _HasTasks; }
    private set
    {
    if (HasTasks == value)
    {
    return;
    }
    _HasTasks = value;
    this.NotifyPropertyChanged("HasTasks");
    }
    }
    #endregion

    #region HasCurrentTask
    private Visibility _HasCurrentTask = Visibility.Collapsed;
    public Visibility HasCurrentTask
    {
    get { return _HasCurrentTask; }
    private set
    {
    if (HasCurrentTask == value)
    {
    return;
    }
    _HasCurrentTask = value;
    this.NotifyPropertyChanged("HasCurrentTask");
    }
    }
    #endregion

    #region Message
    private string _Message;
    public string Message
    {
    get { return _Message; }
    private set
    {
    if (Message == value)
    {
    return;
    }
    _Message = value;
    this.NotifyPropertyChanged("Message");
    }
    }
    #endregion

    مقدار کدها به نظر زیاد میاید اما آنها فقط Property هایی هستند که دادهایی را که قرار است در View به نمایش در آیند، در خود نگه می دارند. تغییر در هر کدام از Property ها موجب بالا آمدن NotifyPropertyChanged خواهد شد.
    کدهای زیر را نیز به انتهای کلاس فوق اضافه کنید:

    // Collections

    #region colTasks
    private ObservableCollection<Task> _colTasks
    = new ObservableCollection<Task>();
    public ObservableCollection<Task> colTasks
    {
    get { return _colTasks; }
    private set
    {
    if (colTasks == value)
    {
    return;
    }
    _colTasks = value;
    this.NotifyPropertyChanged("colTasks");
    }
    }
    #endregion

    کد فوق شبیه یک Property است اما در واقع یک Collection از Task ها است ( به جای یک تک مقدار یا Task).
    هنوز ادامه دارد. لطفا کدهای زیر را نیز به انتهای همان کلاس اضافه کنید:

    // Operations

    #region GetTasks
    private void GetTasks()
    {
    // Clear the current Tasks
    colTasks.Clear();
    // Call the Model to get the collection of Tasks
    TasksModel.GetTasks((Param, EventArgs) =>
    {
    if (EventArgs.Error == null)
    {
    // loop thru each item
    foreach (var Task in EventArgs.Result)
    {
    // Add to the colTasks collection
    colTasks.Add(Task);
    }

    // Count the records returned
    if (colTasks.Count == 0)
    {
    // If there are no records, indicate that
    Message = "No Records Found";

    // Set HasCurrentTask
    HasCurrentTask = Visibility.Collapsed;

    // We have no Tasks so set HasTasks
    HasTasks = Visibility.Collapsed;
    }
    else
    {
    // We have Tasks so set HasTasks
    HasTasks = Visibility.Visible;
    }
    }
    });
    }
    #endregion

    #region GetTask
    private void GetTask(int intTaskID)
    {
    // Call the Model to get the Task
    TasksModel.GetTask(intTaskID, (Param, EventArgs) =>
    {
    if (EventArgs.Error == null)
    {
    // Set the CurrentTask Property
    CurrentTask = EventArgs.Result;

    // Set Visibility
    HasCurrentTask = Visibility.Visible;
    AddVisibility = Visibility.Visible;
    UpdateVisibility = Visibility.Visible;
    DeleteVisibility = Visibility.Visible;
    }
    });
    }
    #endregion

    #region DeleteTask
    private void DeleteTask(Task objTask)
    {
    // Call the Model to delete the Task
    TasksModel.DeleteTask(objTask.TaskID, (Param, EventArgs) =>
    {
    if (EventArgs.Error == null)
    {
    // Set the Error Property
    Message = EventArgs.Result;

    // Set current Task to null
    CurrentTask = null;

    // Update the Tasks list
    GetTasks();

    // Set Visibility
    HasCurrentTask = Visibility.Collapsed;
    AddVisibility = Visibility.Visible;
    UpdateVisibility = Visibility.Collapsed;
    DeleteVisibility = Visibility.Collapsed;
    }
    });
    }
    #endregion

    #region UpdateTask
    private void UpdateTask(Task objTask)
    {
    // Call the Model to UpdateTask the Task
    TasksModel.UpdateTask(objTask, (Param, EventArgs) =>
    {
    if (EventArgs.Error == null)
    {
    // Set the Error Property
    Message = EventArgs.Result;

    // Update the Tasks list
    GetTasks();

    // Set Visibility
    HasCurrentTask = Visibility.Visible;
    AddVisibility = Visibility.Visible;
    UpdateVisibility = Visibility.Visible;
    DeleteVisibility = Visibility.Visible;
    }
    });
    }
    #endregion

    #region InsertTask
    private void InsertTask(Task objTask)
    {
    // Call the Model to Insert the Task
    TasksModel.InsertTask(objTask, (Param, EventArgs) =>
    {
    if (EventArgs.Error == null)
    {
    // Set the CurrentTask Property
    CurrentTask = EventArgs.Result;

    // Update the Tasks list
    GetTasks();

    // Set Visibility
    HasCurrentTask = Visibility.Visible;
    AddVisibility = Visibility.Visible;
    UpdateVisibility = Visibility.Visible;
    DeleteVisibility = Visibility.Visible;
    }
    });
    }
    #endregion

    #region SetToNewTask
    private void SetToNewTask()
    {
    // Create a empty Task
    // so form will be blank
    Task objTask = new Task();

    // Set TaskID = -1 so we know it"s
    // a new Task
    objTask.TaskID = -1;

    // Set the CurrentTask Property
    CurrentTask = objTask;

    // Set Visibility
    HasCurrentTask = Visibility.Visible;
    AddVisibility = Visibility.Collapsed;
    UpdateVisibility = Visibility.Visible;
    DeleteVisibility = Visibility.Collapsed;
    }
    #endregion

    یک سری عملیاتهایی وجود دارد که ViewModel آنها را اجرا خواهد کرد. در واقع توابع یا متدهایی هستند که کارهای واقعی را انجام می دهند. اکثر این متدها صرفاً متدهای Model را فراخوانی می کنند.
    کدهای زیر را به انتهای کلاس اضافه کنید:
    // Commands

    #region GetTasksCommand
    public ICommand GetTasksCommand { get; set; }
    public void GetTasks(object param)
    {
    GetTasks();
    }

    private bool CanGetTasks(object param)
    {
    return true;
    }
    #endregion

    #region GetTaskCommand
    public ICommand GetTaskCommand { get; set; }
    public void GetTask(object param)
    {
    // Get the Task that was passed as a parameter
    Task objTask = (Task)param;

    // Call GetTask to get and set
    // the CurrentTask property
    GetTask(objTask.TaskID);
    }

    private bool CanGetTask(object param)
    {
    // Only allow this ICommand to fire
    // if a Task was passed as a parameter
    return ((param as Task) != null);
    }
    #endregion

    #region DeleteTaskCommand
    public ICommand DeleteTaskCommand { get; set; }
    public void DeleteTask(object param)
    {
    if (CurrentTask.TaskID == -1)
    {
    // This is a new Task
    SetToNewTask();
    }
    else
    {
    // This is an Existing Task
    DeleteTask(CurrentTask);
    }
    }

    private bool CanDeleteTask(object param)
    {
    // Do not allow if there is no Current Task
    return (CurrentTask != null);
    }
    #endregion

    #region UpdateTaskCommand
    public ICommand UpdateTaskCommand { get; set; }
    public void UpdateTask(object param)
    {
    if (CurrentTask.TaskID == -1)
    {
    // This is a new Task
    InsertTask(CurrentTask);
    }
    else
    {
    // This is an Update
    UpdateTask(CurrentTask);
    }
    }

    private bool CanUpdateTask(object param)
    {
    // Do not allow if there is no Current Task
    return (CurrentTask != null);
    }
    #endregion

    #region AddNewTaskCommand
    public ICommand AddNewTaskCommand { get; set; }
    public void AddNewTask(object param)
    {
    SetToNewTask();
    }

    private bool CanAddNewTask(object param)
    {
    return true;
    }
    #endregion

    این کدها نیز ICommand ها بودند. کدهایی که توسط View فراخوانی خواهند شد.

    در Visual Studio از منوی Build گزینه Build RIATasks را انتخاب کنید. پروژه می بایست بدون هرگونه خطای Build شود.
    در مرحله بعدی به ساخت View و ارتباط آن با Command ها و Property ها خواهیم پرداخت.

  7. #7
    کاربر دائمی آواتار piroozman
    تاریخ عضویت
    مهر 1386
    محل زندگی
    تهران
    سن
    48
    پست
    217

    RIATasks: یک مثال ساده از CRUD در Silverlight

    قسمت هفتم:
    View



    MainPage.xaml را در Expression Blend باز کنید.


    پروژه در Expression Blend باز خواهد شد.

    روی LayoutRoot در پنجره Object and Timeline کلیک کرده و در پنجره Properties عبارت DataContext را در جعبه متن Search Properties تایپ کنید.
    روی دکمه New کلیک کنید.

    MainPageModel را از فضای نام {}RIATasks انتخاب کرده و Ok کنید (می توانید با تایپ MainPageModel در جعبه متن Search Objects شی مورد نظر را به راحتی بیابید).

    به زبانه Data رفته و MainPageModel را بسط دهید (زیر بخش Data Context).
    در این قسمت شما تمامی Property ها، Collection ها و ICommand های Public ی را که در MainPageModel وجود دارند را خواهید دید.
    ایجاد Sample Data

    این کار موجب می شود که طراحی فرم راحتر شود و نیز شما امکان مشاهده داده های نمونه نیز وجود خواهد داشت.
    در پنجره Data روی آیکون Create sample data کلیک کنید.

    گزینه Create Sample Data from Class . . . را انتخاب کنید.

    در فضای نام{}RIATasks کلاس MainPageModel ار انتخاب کرده و روی OK کلیک کنید.

    MainPageModelSampleData را مشاهده می کنید.
    ادامه مراحل ساخت View را در انشالله در قسمت بعدی.

  8. #8
    کاربر دائمی آواتار piroozman
    تاریخ عضویت
    مهر 1386
    محل زندگی
    تهران
    سن
    48
    پست
    217

    RIATasks: یک مثال ساده از CRUD در Silverlight

    قسمت هشتم:
    ساخت View

    روی colTasks در قسمت Sample Data کلیک کنید . . .

    . . . و آن را روی صفحه رها کنید.

    با این کار، یک ListBox با نمونه داده ها ایجاد خواهد شد.
    نکته: در حال run-time اطلاعات واقعی اطلاعات نمونه نشان داده نخواهد شد.


    در Properties مربوط به ListBox مقادیر HorizontalAlignment به Left و VerticalAlignment را به Top تغییر دهید.

    روی ListBox کلیک راست کرده و گزینه
    Edit additional Templates > Edit Generated Items > Edit Current
    را انتخاب کنید.

    در پنجره Object and Timeline روی سومین TextBlock کلیک کنید.

    در قسمت Properties مربوط به TextBlock در قسمت Text گزینه Advanced options :

    گزینه Data Binding . . . ر انتخاب کنید.
    نکته: نسخه Expression Blend مربوط به آموزش موجود در این مقاله 4 می باشد. در نسخه ی بالاتر ممکن است عبارات قدری متفاوت باشد. به طور مثال به جای عبارت Data Binding . . . شما عبارت Crate Data Binding . . . را خواهید دید.

    همانطور که می بینید این TextBlock به TaskName مقید(بایند) شده است. این تنها TextBlock ای است که می خواهیم در ListBox نمایش داده شود.

    در قسمت Objects and Timeline سایر TextBlock ها را حذف کنید.

    بر روی آیکون Return scope کلیک کنید.

    همانطور که می بینید ListBox شکل خود را یافته است.

    حالا یک کنترل گرید انتخاب کنید.

    Grid را درست بعد از ListBox و در مجاور آن قرار دهید.

    با شناور نمودن موس در لبه های گرید و با فشردن دکمه چپ موس یک سلول ایجاد کنید.

    از جعبه ابزار یک TexBox را گرفته . . .

    . . . آنرا کشیده و روی Grid رها کنید.

    از پنجره Data، گزینه TaskName را گرفته . . .

    . . . و سپس آنرا روی TextBox رها کنید.

    در Properties مربوط به TextBOx

    • Width و Height را به Auto تغییر دهید.
    • Horizontal و Vertical Alignment را مطابق شکل تنظیم کنید.
    • مقدار Margins را برابر صفر قرار دهید.


    یک TextBox بر روی گرید قرار دهید.

    در Properties مربوط به TextBOx

    • Width و Height را به Auto تغییر دهید.
    • Horizontal و Vertical Alignment را مطابق شکل تنظیم کنید.
    • مقدار Margins را برابر صفر قرار دهید.


    از پنجره Data، گزینه TaskDescription را انتخاب کرده و روی این TextBox رها کنید.

    دو TextBlock با متن Name و Description مطابق شکل در کنار TextBox های مربوطه قرار دهید.(برای این کار باید Text Properties. آنرا تغییر دهید)

    در قسمت Tool Bar روی ابزار Button کلیک کنید.

    در قسمت Tool Bar روی ابزار Button کلیک کنید.

    مقدار Content آنرا به Add تغییر دهید.

    دو کلید Update و Delete مطابق شکل به بالای ListBox اضافه کنید.
    (ما در مراحل بعدی رویدادهای کلیک مربوط به این دکمه ها را تنظیم خواهیم کرد.)
    تنظیمات مربوط به Visibility
    الان تمامی کنترل های مورد نیاز روی صفحه قرار دارند، و هم اکنون می خواهیم Visibility را به کنترل های مختلف قلاب کنیم(hook up).

    روی پنجره Object and Timeline روی کنترل Grid کلیک کنید.

    در Properties مربوط به Grid، Advanced options مربوط به Visibility را انتخاب کنید.

    گزینه Data Binding . . .(در نسخه 5 Create Data Binding . . ) را انتخاب کنید.

    گرید را به HasCurrentTask مقید نموده و روی OK کلیک کنید.

    مابقی Visibility Properties را مطابق دیاگرام فوق به کنترل ها قلاب کنید.

    نکته: اگر مقید سازی خصیصه Visibility موجب شود که برخی از کنترل ها در حال Desing (یا همان طراحی) دیده نشوند، می توانید فایل sample data را ویرایش کنید و . . .

    . . . مقادیر آنها را به مقدار Visible تغییر دهید.
    استفاده از رفتارها (Behaviors)
    در این قسمت از رفتار InvokeCommandAction به منظور این که دکمه ها ICommand های تعریف شده در View Model را اجرا کنند، استفاده خواهیم کرد.
    استفاده از Behaviors
    در این قسمت از رفتار InvokeCommandAction به منظور این که دکمه ها ICommand های تعریف شده در View Model را اجرا کنند، استفاده خواهیم کرد.
    اضافه کردن دکمه

    از طبقه مربوط به Behaviors کنترل InvokeCommadnAction را انتخاب کنید.(برای یافتن راحتر ان می توانید عبارت Invoke را در جعبه متن Search بنویسید).

    و در پنجره Object and Timeline روی دکمه Add رها کنید.

    در Properties مربوط به این Behavior:

    • گزینه Click را در قسمت EventName انتخاب کنید.
    • در قسمت Command Properties بر روی آیکون Data bind کلیک کنید.


    به زبانه Data Context رفته، سپس گزینه AddNewTaskCommand را انتخاب کرده و روی دکمه OK کلیک کنید.

    رفتار های InvokeCommandAction را به دکمه های Update، Delete و Add مطابق دیاگرام فوق اضافه کنید.
    انتخاب یک Task از ListBox


    • یک InvokeCommandAction به ListBox اضافه کنید.
    • گزینه SelectionChanged را در قسمت EventName انتخاب کنید.
    • در قسمت Command بر روی آیکون Data bind کلیک کنید.


    گزینه GetTaskCommand را انتخاب و روی OK کلیک کنید.

    در قسمت CommandParameter بر روی Advanced Options کلیک کنید.

    درقسمت ListBox گزینه SelectedItem را انتخاب و OK کنید.
    افزودن Style

    با کلیک بر روی این لینک در مورد ResourceDictionary و نحوه به کارگیری آنها بیشتر مطالعه کنید.
    Build و اجرای پروژه

    در پنجره Projecties، روی پروژه RIATasks.Web کلیک راست کرده و گزینه Startup Project را انتخاب کنید.

    روی صفحه Default.aspx کلیک راست کرده و گزینه Startup را انتخاب کنید.
    برای Build و اجرای پروژه از کلید F5 استفاده کنید.

    پروژه کامل شد.

  9. #9
    کاربر دائمی آواتار piroozman
    تاریخ عضویت
    مهر 1386
    محل زندگی
    تهران
    سن
    48
    پست
    217

    RIATasks: یک مثال ساده از CRUD در Silverlight

    قسمت نهم(آخر):
    وقتی می خواهید کد کمتری داشته باشید از View Model استفاده کنید.
    مقید سازی ترکیب شده با INotifyPropertyChanged می تواند شما را از نوشتن کدهای زیاد نجات دهد. استفاده از View Model موجب می شود از ویژگیهای بسیار مفید موجود در Microsoft Expressions Blend بهره مند گردید. View Model همچنین یک الگوی ساده برای پیروی از آن است، بنابراین شما می توانید به سرعت و به راحتی Properties، Collections و ICommands را پیاده سازی کنید.
    "کد سفارشی" (کد نویسی) واقعی شما در قسمت "Operations" هایی است که در قسمت View Model وجود دارد. شما می بینید که کد زیادی وجود نداشته و قسمت اعظم آن صرفا جهت فراخوانی Model و تنظیمات Properties در View Model نوشته شده است. در ضمن توجه داشته باشید که وقتی یک شی مانند یک Task به عنوان Task جاری انتخاب می شود، هیچ نیازی نیست که هریک از فیلد های موجود در شی Task تفکیک شود و پردازش هر یک از آنها به طور جداگانه انجام شود. ما کل شی Task را میان Model، View Model و View رد و بدل می کنیم.
    این که ما می توانیم Property ها، مانند آنچه که در اشیاء سفارشی مانند Task و Visibility وجود داشت، را در View نمایش دهیم بسیار مفید می باشد و نگرانی نحوه پیاده سازی آنها را به طراحان می سپاریم. با فرض اینکه ما طراح هم باشیم، می توانیم از ویژگیهای Drag & Drop نرم افزار Expression Blend به سرعت و با دقت طراحی های مربوط به User Interface را انجام دهیم.
    برنامه نویس می تواند صرفاً در نحوه ورود و خروج داده ها در View Model از طریق Model، و به تولید و اجرا درآودن لایه های تجاری تمرکز داشته باشد.
    به عقیده من یک برنامه نویس متوجه خواهد شد که ما از ویژگی LESS CODE نهفته در View Model بهره مند شده ایم و اگر از این الگو استفاده نمی شد مطمئناًً با حجم بسیار بیشتر کد نویسی مواجه می شدیم.
    حداقل، بسیاری از برنامه نویسانی که من با آنها کار کرده ام، تجربه بسیار لذت بخشی را در بهره مندی از این الگو داشته اند، چون می توانند بر روی منطق رویه ها تمرکز داشته باشند.
    پروژه را نیز می توانید در انتهای همین مقاله دانلود کنید.
    درباره نویسنده:

    Michael Washington is a Microsoft Silverlight MVP. He is a Silverlight developer and an ASP.NET, C#‎‎‎, and Visual Basic programmer.
    He is a DotNetNuke Core member and has been involved with DotNetNuke for over 4 years. He is the Co-Author of Building Websites with DotNetNuke (4 and 5).
    He is one of the founding members of The Open Light Group (http://openlightgroup.net).
    He is the founder of http://LightSwitchHelpWebsite.com
    He has a son, Zachary and resides in Los Angeles with his wife Valerie

    .
    موفق باشید . . .
    فایل های ضمیمه فایل های ضمیمه

تاپیک های مشابه

  1. سوال: یک مثال ساده و یک پرسش در رابطه با نمودار DFD (همراه با تصویر)
    نوشته شده توسط Jason.Bourne در بخش تحلیل و طراحی نرم افزار
    پاسخ: 0
    آخرین پست: شنبه 13 تیر 1388, 11:20 صبح
  2. سوال: یک مثال ساده در مورد CSocket , CArchive نیاز دارم
    نوشته شده توسط Cave_Man در بخش برنامه نویسی با MFC و ++Visual C
    پاسخ: 2
    آخرین پست: یک شنبه 13 بهمن 1387, 21:43 عصر
  3. خبر: دانلود یک مثال ساده
    نوشته شده توسط kiosksoft در بخش ASP.NET Web Forms
    پاسخ: 0
    آخرین پست: شنبه 27 مهر 1387, 15:22 عصر
  4. سوال: مشکل در بر قراری ارتباط بین جداول در یک مثال ساده
    نوشته شده توسط DotNet_King در بخش SQL Server
    پاسخ: 10
    آخرین پست: چهارشنبه 22 خرداد 1387, 10:18 صبح
  5. یک مثال ساده
    نوشته شده توسط free_user در بخش VB.NET
    پاسخ: 2
    آخرین پست: پنج شنبه 21 مهر 1384, 21:56 عصر

برچسب های این تاپیک

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •