http://www.tabatabaei.info/csharpsamples/CSharpTutorial.pdf
فیلم های آموزشی مایکروسافت برای کسانی که می خواهند برنامه نویسی با ابزارهای مایکروسافت را بیاموزند:
http://ngm.nationalgeographic.com/2008/08/iran-archaeology/iran-photography
ممنون از اینکه از وبلاگ من بازدید کردید. امیدوارم مفید باشه براتون.
بعضی وقتا گذاشتن یه CheckBox برای کاربرا که بتونن همه CheckBox های توی یه لیست رو تیک بزنن (مثل یاهو یا gmail) مشتری ها رو خیلی خوشحال می کنه. اگه از کنترل های ASP مثل GridView استفاده می کنید و نمی دونید چطوری بدون PostBack شدن صفحه و فقط با کد های JavaScript پس جای درستی اومدید :D اصلا هم مهم نیست که دارید از MasterPage، AJAX، UserControl یا هر چیز دیگه ای استفاده می کنید یا نه. این کد به هر حال درست کار می کنه
اول یه ستون از نوع Template اضافه کنید که توش یه دونه کنترل CheckBox باشه. این طوری کاربر کنار هر رکورد اطلاعاتی می تونه یه تیک بزنه. برای همین ستون یه Header هم تعریف کنید که توش یه CheckBox باشه. کاربر می خواد با زدن این تیک، همه گزینه ها رو انتخاب کنه (Select All/UnSelect All)
<HeaderTemplate>
<asp:CheckBox ID="chkSelectAll" runat="server" AutoPostBack="false"/>
HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkSelect" runat="server" AutoPostBack="false" />
ItemTemplate>
حالا می خوایم کاری کنیم که با کلیک روی chkSelectAll یه کد جاوا اجرا بشه. این کار باید RunTime انجام بشه. یعنی بعد از اینکه یه Id به صورت ClientSide برای chkSelectAll ایجاد شد. (البته یه پیش بینی هایی هم می شه کرد.
if ((e.Row.RowType == DataControlRowType.Header))
{
((CheckBox)e.Row.FindControl("chkSelectAll")).Attributes.Add("onclick", "javascript:ToggleSelect ('" + ((CheckBox)e.Row.FindControl("chkSelectAll")).ClientID + "')");
}
این کد باعث می شه که اگه کاربر روی CheckBox روی Header کلیک کرد (شرط if(e.Row…)) تابع جاوا به اسم ToggleSelect صدا زده بشه و Id ایجاد شده برای این کنترل هم به تابع پاس داده می شه. تابع جاوا هم باید به صفحه اضافه بشه.
<script type="text/javascript">
function ToggleSelect(id)
{
var frm = document.forms[0];
for (i=0;i
{
if (frm.elements[i].type == "checkbox")
{
frm.elements[i].checked = document.getElementById(id).checked;
}
}
}
script>
حالا يه صفحه اي كه اين Pager رو تو خودش داره. يه DropDownList هم اضافه كردم كه كاربر بتونه تعداد ركوردهاي هر صفحه رو انتخاب كنه. اينجا از Event ي كه تعريف كرده بوديم براي نمايش شماره صفحه اي كه كاربر داره روش كليك مي كنه استفاده مي كنيم. يه تابع داريم كه اطلاعات رو از بانك اطلاعاتي بارگذاري مي كنه. مي تونيد به اين تابع شماره صفحه و تعداد ركورد و فيلتر و فيلدي براي مرتب سازي داده ها هم ارسال كنيد.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Assembly="FanaCustomControls" Namespace="FanaCustomControls" TagPrefix="fcc" %>
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Pagetitle>
head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblMessage" runat="server">asp:Label><br />
<asp:DropDownList ID="ddlPageSize" runat="server">
<asp:ListItem>10asp:ListItem>
<asp:ListItem>20asp:ListItem>
<asp:ListItem>100asp:ListItem>
asp:DropDownList>
<fcc:DataPaging ID="DataPaging1" runat="server" />
div>
form>
body>
html>
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
DataPaging1.SelectedPageChanged += new EventHandler(SelectedPageChanged);
DataPaging1.PageSize = Convert.ToInt32(ddlPageSize.SelectedValue);
int RecordCount = 0;
//RecordCount=SELECT * FROM Table WHERE Condition
DataPaging1.RecordCount = RecordCount;
ViewState["RecordCount"] = RecordCount;
BindDataList(1, Convert.ToInt32(ddlPageSize.SelectedValue), "Date", "[Name] LIKE '%hh%'");
}
catch (Exception exp)
{
lblMessage.Text = exp.Message;
}
}
protected void SelectedPageChanged(object sender, EventArgs e)
{
Response.Write(string.Format("شما در حال مشاهده صفحه {0} هستید", DataPaging1.PageIndex.ToString()));
BindDataList(DataPaging1.PageIndex, Convert.ToInt32(ddlPageSize.SelectedValue), "Date", "[Id]>0");
}
private void BindDataList(int pageIndex, int pageSize, string sortField, string filterString)
{
try
{
string _ConnectionString = "";
SqlConnection connection = new SqlConnection(_ConnectionString);
SqlCommand command = new SqlCommand();
command.Connection = connection;
//You should bind your datalist to database here using a query like this
string query = "SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY @SortField) AS RowNum, [Field1], [Field2] FROM [TableName] WHERE @FilterString) AS MainQuery WHERE RowNum>=@StartRecord AND RowNum<@EndRecord ";
command.CommandText = query;
command.Parameters.AddWithValue("@SortField", sortField);
command.Parameters.AddWithValue("@FilterString", filterString);
int startRecord = Convert.ToInt32(ViewState["RecordCount"]) / pageSize * pageIndex;
int endRecord = startRecord + pageSize;
command.Parameters.AddWithValue("@StartRecord", startRecord);
command.Parameters.AddWithValue("@EndRecord", sortField);
connection.Open();
SqlDataReader dataReader;
dataReader = command.ExecuteReader();
while (dataReader.Read())
{
//Enter Records In a ArrayList, DataTable Or Dataset
}
connection.Close();
}
catch (Exception exp)
{
lblMessage.Text=exp.Message;
}
}
}
چند تا كد آماده ديدم كه اين كار رو انجام دادن اما اكثرا اطلاعات رو از بانك اطلاعاتي Load مي كنن و صفحه بندي اطلاعات رو توي Presentation layer يا Data Access Layer انجام مي دن. اما قابليتي كه SQLSERVER 2005 داره اين امكان رو مي ده كه فقط ركورد هايي رو كه مي خوايم به كاربر نمايش بديم رو Load كنيم. اين جوري Performance كار خيلي بالا مي ره.
براي اينكه بتونيم يه Data Paging محكمه پسند ارائه بديم چند تا كار بايد بكنيم. اول يه مثال از دستوري كه Paging داده ها رو انجام ميده مي زنم كه ببينيد sql server اين امكان رو چطوري پشتيباني مي كنه.
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY [Id]) AS RowNum, [Field1], [Field2] FROM [TableName] WHERE [Name]='Fana') AS MainQuery WHERE RowNum>=10 AND RowNum<20
با يه همچين كدي مي تونيد ركوردهاي 10 تا 20 رو از بانك اطلاعاتي Load كنيد. براي اينكه بتونيد به تعداد صفحات اطلاعات براي كاربر لينك بزاريد، توصيه مي كنم يه كنترل درست كنيد كه اين كار رو براتون انجام بده. با استفاده از ويژوال استوديو مي تونيد يه Web Custom Control درست كنيد كه برنامه نويس فقط تعداد ركوردها رو بش پاس بده و نگران بقيه قسمت هاي كار نباشه. كد يه Custom Control رو اينجا آوردم كه با همون شرايطي كه نوشتم كار مي كنه. درضمن يه Event هم بش اضافه كردم كه برنامه نويس مي تونه تشخيص بده كاربر درخواست يه Page جديد داشته يانه؟ اين كنترل 5تا لينك رو نمايش مي ده (Section 1) و با كليك كاربر بر روي لينك صفحه پنجم، اين 5تا لينك، شماره هاشون تبديل به 3 تا 7 مي شه(Section2) اين طوري كاربر هميشه 5 تا لينك توي صفحه داره كه هرچقدر جلو بريم شماره هاي لينك ها افزايش پيدا مي كنه
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
[assembly:TagPrefix("FanaCustomControls","fcc")]
namespace FanaCustomControls
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:DataPaging runat=server>{0}:DataPaging>")]
public class DataPaging : WebControl
{
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
#region Properties
private int _SectionIndex = 1;
private int _SectionCount = 1;
private int _PageSize = 10;
///
/// تعداد رکوردهای هر صفحه. به صورت پیش فرض هر صفحه 10 رکورد را نمایش می دهد
///
public int PageSize
{
get { return _PageSize; }
set { _PageSize = value; }
}
private long _RecordCount;
///
/// تعداد کل رکوردهایی که قرار است صفحه بندی شوند
///
public long RecordCount
{
get { return _RecordCount; }
set
{
_RecordCount = value;
//تعیین تعداد صفحات
PageCount = (int)value / _PageSize + 1;
}
}
private int _PageCount;
///
/// تعداد کل صفحات
///
public int PageCount
{
get { return _PageCount; }
set
{
_PageCount = value;
int counter = 5;
_SectionCount = 1;
while (counter < value)
{
counter += 2;
_SectionCount++;
}
CreateChildControls();
}
}
private int _PageIndex = 1;
///
/// شماره صفحه جاری
///
public int PageIndex
{
get { return _PageIndex; }
set { _PageIndex = value; }
}
#endregion
#region ControlsOnTheForm
private LinkButton lnkBtn1;
private LinkButton lnkBtn2;
private LinkButton lnkBtn3;
private LinkButton lnkBtn4;
private LinkButton lnkBtn5;
#endregion
#region Events_Methods
public EventHandler SelectedPageChanged;
public void OnBtn1Click(Object o, System.EventArgs ea)
{
try
{
_PageIndex = Convert.ToInt32(lnkBtn1.Text);
if (_SectionIndex > 1)
{
ReduceSectionIndex();
}
if (SelectedPageChanged != null)
{
SelectedPageChanged(this, EventArgs.Empty);
}
}
catch
{
throw;
}
}
public void OnBtn2Click(Object o, System.EventArgs ea)
{
try
{
_PageIndex = Convert.ToInt32(lnkBtn2.Text);
if (SelectedPageChanged != null)
{
SelectedPageChanged(this, EventArgs.Empty);
}
}
catch
{
throw;
}
}
public void OnBtn3Click(Object o, System.EventArgs ea)
{
try
{
_PageIndex = Convert.ToInt32(lnkBtn3.Text);
if (SelectedPageChanged != null)
{
SelectedPageChanged(this, EventArgs.Empty);
}
}
catch
{
throw;
}
}
public void OnBtn4Click(Object o, System.EventArgs ea)
{
try
{
_PageIndex = Convert.ToInt32(lnkBtn4.Text);
if (SelectedPageChanged != null)
{
SelectedPageChanged(this, EventArgs.Empty);
}
}
catch
{
throw;
}
}
public void OnBtn5Click(Object o, System.EventArgs ea)
{
try
{
_PageIndex = Convert.ToInt32(lnkBtn5.Text);
if (_SectionCount > _SectionIndex)
{
AddSectionIndex();
}
if (SelectedPageChanged != null)
{
SelectedPageChanged(this, EventArgs.Empty);
}
}
catch
{
throw;
}
}
public void AddPageIndex(int count)
{
try
{
_PageIndex += count;
int Start = _SectionIndex + _SectionIndex - 1;
if (_PageIndex == Start)
{
ReduceSectionIndex();
}
if (_PageIndex == Start + 4)
{
AddSectionIndex();
}
}
catch
{
throw;
}
}
public void ReducePageIndex(int count)
{
try
{
_PageIndex -= count;
int Start = _SectionIndex + _SectionIndex - 1;
if (_PageIndex == Start)
{
ReduceSectionIndex();
}
if (_PageIndex == Start + 4)
{
AddSectionIndex();
}
}
catch
{
throw;
}
}
private void AddSectionIndex()
{
try
{
_SectionIndex += 1;
CreateChildControls();
}
catch
{
throw;
}
}
private void ReduceSectionIndex()
{
try
{
_SectionIndex -= 1;
CreateChildControls();
}
catch
{
throw;
}
}
#endregion
protected override void CreateChildControls()
{
base.CreateChildControls();
try
{
this.Controls.Clear();
//مدیریت دکمه های بعدی، قبلی، اولین و آخرین صفحه
int _Start = 1;
_Start = _SectionIndex + _SectionIndex - 1;
if (_Start > 1)
{
//imgBtnPrevious.Enabled = true;
//imgBtnFirst.Enabled = true;
}
if (_PageIndex < _PageCount)
{
//imgBtnLast.Enabled = true;
//imgBtnNext.Enabled = true;
}
if (_PageIndex > 1)
{
//imgBtnPrevious.Enabled = true;
}
//ایجاد لینک صفحات
if (_PageCount >= _SectionIndex + _SectionIndex - 1)
{
lnkBtn1 = new LinkButton();
lnkBtn1.Text = Convert.ToString(_SectionIndex + _SectionIndex - 1);
lnkBtn1.Click += new EventHandler(OnBtn1Click);
this.Controls.Add(lnkBtn1);
}
if (_PageCount >= _SectionIndex + _SectionIndex)
{
lnkBtn2 = new LinkButton();
lnkBtn2.Text = Convert.ToString(_SectionIndex + _SectionIndex);
lnkBtn2.Click += new EventHandler(OnBtn2Click);
this.Controls.Add(lnkBtn2);
}
if (_PageCount >= _SectionIndex + _SectionIndex + 1)
{
lnkBtn3 = new LinkButton();
lnkBtn3.Text = Convert.ToString(_SectionIndex + _SectionIndex + 1);
lnkBtn3.Click += new EventHandler(OnBtn3Click);
this.Controls.Add(lnkBtn3);
}
if (_PageCount >= _SectionIndex + _SectionIndex + 2)
{
lnkBtn4 = new LinkButton();
lnkBtn4.Text = Convert.ToString(_SectionIndex + _SectionIndex + 2);
lnkBtn4.Click += new EventHandler(OnBtn4Click);
this.Controls.Add(lnkBtn4);
}
if (_PageCount >= _SectionIndex + _SectionIndex + 3)
{
lnkBtn5 = new LinkButton();
lnkBtn5.Text = Convert.ToString(_SectionIndex + _SectionIndex + 3);
lnkBtn5.Click += new EventHandler(OnBtn5Click);
this.Controls.Add(lnkBtn5);
}
}
catch
{
throw;
}
this.ChildControlsCreated = true;
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//Label lblMessage = new Label();
//lblMessage.Text = "صفحه شمار";
//this.Controls.Add(lblMessage);
this.EnsureChildControls();
}
}
}
تا اونجايي كه تونستم توي كد Comment گذاشتم. هرجاش كه مفهوم نبود و توضيح لازم داشت بگيد اضافه كنم
نمونه پروژه آماده c# و visual basic برای کسانی که می خوان با معماری های درست آشنا بشن. می تونید پروژه ها رو دانلود کنید. هم می تونید به عنوان الگوی برنامه نویسی ازشون ایده بگیرید و هم می تونید به عنوان end user اونا رو upload کنید و استفاده کنید. من چندتاشون رو دانلود کردم. بعضی ها با .net 2 و بعضی هاشون هم با .net 3.5 کار شدن. اکثرا قابل استفاده روی بانک های اطلاعاتی مختلف از جمله sql server 2000, sql server 2005, sql server 2008, oracle 10g و ... هستن. بینشون پروژه ساده مثل کاریابی و فروشگاه و پروژه های پیچیده تر مثل یه CRM (Customer Relationship Management) هست که خیلی جالب به نظر می رسه. جالبه که وقتی برای دانلود وارد سایت خودشون می شی می بینی که دارن از DotNetNuke استفاده می کنن J فرهنگ openness رو با جون و دل قبول کردن و تکرار کردن کار تکراری رو گذاشتن کنار.
البته اینم بگم که این پروژه های آماده به درد دانشجوهای بی سوادی که باید کد رو به استادشون توضیح بدن نمی خوره. چون اصولا پروژه دانشجویی نیستن J
آدرس:
http://www.asp.net/community/projects
http://www.asp.net/downloads/sandbox
برعکس همه Document های دیگه من Linq رو از آخرش شروع می کنم چون به نظر من پرکاربرد ترین بخش Linq ارتباط با بانک های اطلاعاتی Relational خارجیه مثل SQLServer. بخشی از Linq با اسم Linq to Sql امکان دسترسی به یک Object Model بر اساس Entity های موجود در سیستم رو به ما می ده. به شکل ساده تر: شما می تونید یک لایه تعریف کنید که یه Abstraction از بانک اطلاعاتی به ما ارائه می ده که ما با استفاده از Linq می تونیم Query های خودمون رو روی این Object Model انجام بدیم و Linq to Sql این Query ها رو روی بانک اطلاعاتی انجام خواهد داد.
به این ترتیب شما چنین کدی می نویسید
var query =
from c in Company
where c.Name == "FANA"
select new {c.Id, c.Name };
این Query تبدیل به چنین کدی می شه:
SELECT Id, Name
FROM Company
WHERE Name = 'FANA'
Entities(موجودیت ها)
برای هر موجودیت در بانک اطلاعاتی باید معادلی از نوع کلاس داشته باشیم. هر جدول بانک اطلاعاتی یک کلاس معادل خواهد داشت که تمامی Attribute های آن معادل فیلدهای جدول هستند. البته لازم نیست حتما تمامی فیلدهای جدول در کلاس معادل سازی بشن اما حتما باید همه Attribute ها جزو فیلدهای جدول باشن.
این یه مثال برا یه جدول به اسم Company و دارای فیلدهای Id، Name و State
[Table(Name="Company")]
Public class Customer {
[Column] public string Id;
[Column] public string Name;
[Column(Name="Ostan")] public string State;
}
همونطور که می بینید فیلدState توی کلاس ما به Ostan تغییر نام پیدا کرده. اینطوری می تونیم فیلدهای بانک اطلاعاتی رو با نامهای دیگه توی کلاس داشته باشیم. البته برای تولید کد این کلاس ها شما می تونید از یه روش خیلی راحت تر استفاده کنید.
توی مطلب قبلی (عدم استفاده از DataSet قسمت سوم ) نوشته بودم که باید اطلاعات ConnectionString رو توی یه کلاس دیگه ذخیره کنیم. یه همچین کدی هم نوشته بودم
_connectionString = clsConfiguration.ConnectionString;
من همیشه یه کلاس ایجاد می کنم به اسم clsConfiguration که اطلاعات ConnectionString و پیکربندی های دیگه رو توش ذخیره می کنم. برا اینکه استفاده کردن از این متغیرها ساده باشه دو راه داریم. یا اینکه متغیر ها رو از نوع Static تعریف کنیم و یا اینکه Const باشن. اینطوری دیگه لازم نیست یه Instance از روی کلاس clsConfiguration بسازیم. کد کلاس مورد نظر اینطوریه
using System;
using System.Collections.Generic;
using System.Text;
namespace HamidDarabi
{
class clsConfiguration
{
public const string ConnectionString = "Data Source='ServerName';Initial Catalog=MyDataBaseName;UID='SQLServerUserName'; Password='SQLServerPassword'";
}
}