احساس می کنم یه توضیحی اینجا قرار بدم بد نباشه شاید بتونه کمکت کنه تا تویه هر کنترل دیتایی که خواستی قرارش بدی:
خب یه گریدویو قرار میدی تویه صفحه و به شکل زیر بانک رو روش بایند می کنی که من اینو تویه این فایل که ضمیمه کردم، داخل یه تابع قرار دادم که با لود شدن صفحه اطلاعات رو از دیتابیس رویه گریدویو قرار میده:
private void AddRecord()
{
string strConnString = SqlDataSource1.ConnectionString;
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection(strConnString))
{
string strQuery = "SELECT * FROM tbl_sample";
SqlCommand cmd = new SqlCommand(strQuery,con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
i++;
}
dr.Close(); con.Close();
s1 = new string[i];
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
con.Open();
sda.SelectCommand = cmd;
sda.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
}
حالا این تابع رو در Page_Load قرار میدیم:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.AddRecord();
}
}
حالا نوبت قرار دادن گریدویو هست:
<asp:GridView ID="GridView1" runat="server" Width="550px"
AutoGenerateColumns="false" dir="rtl"
AlternatingRowStyle-BackColor="#C2D69B" HeaderStyle-BackColor="green"
ShowFooter="true" >
<HeaderStyle ForeColor="White" />
<Columns>
<asp:TemplateField HeaderText="article">
<ItemTemplate>
<%# Eval("article")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="g1">
<ItemTemplate>
<%# Eval("g1")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="g2">
<ItemTemplate>
<%# Eval("g2")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:RadioButtonList ID="RadioButtonList1" runat="server" ToolTip="<%# (z++) %>"
OnSelectedIndexChanged="RadioButtonList1_SelectedI ndexChanged" AutoPostBack="True">
<asp:ListItem Value="1">first</asp:ListItem>
<asp:ListItem Value="2">second</asp:ListItem>
</asp:RadioButtonList>
<%= s1[j] %>
<% j++; %>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<AlternatingRowStyle BackColor="#C2D69B" />
</asp:GridView>
همینجور که میبنید گریدویو دارای یه RadioButtonList هست که قراره با تغییر گزینه انتخاب شده پیغامی رو زیر این رادیو باتن ها نمایش بده.
این کنترل دارای خاصیتی هست که بهش میگن AutoPostBack و برای اینه که اگه گزینه ای رو انتخاب کردیم یک عمل PostBack اتفاق بیافته
اگه این پروپرتی برابر با مقدار True نباشه هیچ وقت عمل PostBack اتفاق نمی افته و بنابراین رویداد OnSelectedIndexChanged این کنترل رخ نخواهد داد.
خب قراره ما اینجا به جای استفاده از لیبل از یه متغیر برای نمایش پیغام استفاده کنیم. می تونیم کد زیر رو در رویداد OnSelectedIndexChanged لیست رادیوباتن قرار بدیم:
protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)
{
RadioButtonList r = (RadioButtonList)sender;
s ="گزینه با موفقیت ثبت شد";
}
و متغیر s رو که بصورت سراسری و با قابلیت فراخوانی در صفحه طراحی، تعریف کردیم رو مقدار دهی کنیم.
برای نمایش متغیر s هم می تونیم کد زیر زو در انتهای رادیوباتن ها قرار بدیم:
<%=s %>
اما این یه مشکلی داره و اونم اینه که این متغیر در تمام سطرهای گریدویو تکرار میشه و با انتخاب رادیوباتن اول در سطر اول، این متغیر در تمامی سطرها مقدار دهی میشه و در تمامی اونها به نمایش در میاد درحالی که ما در سطر اول رادیوباتنی رو انتخاب کردیم و فقط در این سطر باید به نمایش در بیاد. بنابراین باید هر سطری برای خود یک متغیر جداگانه داشته باشه
همینطور که ملاحظه کردید، شبه کدی که در بالا ذکر کردم دارای اشکال هست و باید اصلاح بشه. بهترین روش هم اینه که از آرایه استفاده کنیم.
اما مشکل جدیدی که در آرایه به وجود میاد اینه که این آرایه باید چند اندیس داشه باشه؟ شاید تعداد اندیس ها از تعداد سطرهای گریدویو کمتر باشه اونوقت این آرایه بعد از تکرار سطر های گریدویو نهایتا کم میاره و برنامه با پیغام خطا مواجه میشه
برای حل این مشکل من از این روش استفاده کردم:
.
.
.
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
i++;
}
dr.Close(); con.Close();
s1 = new string[i];
.
.
.
توسط حلقه while و تابع dr.Read() مقدار متغیر i رو افزایش میدیم تا اینکه این متغیر با تعداد سطرهای جدول بانک برابر بشه و تعداد اندیس های آرایه s1 رو با این متغیر مانند کد بالا تعیین می کنیم.
حالا نوبت اینه که هر یک از اندیس های آرایه s1 رو در هر سطر قرار بدیم.
یک نکته ای که اینجا باید بهش دقت کرد اینه که کنترل دیتایی مثل گریدویو یا ریپیتر یا دیتاویو، مثل یه حلقه عمل می کنن، پس کافیه ما متعیری رو داخل اون کنترل بزاریم به طوری که هر بار یک واحد بهش اضافه بشه و اون میشه شماره اندیس مورد نظر آرایه s1 برای هر سطر؛ بنابراین این کد رو در زیر رادیو باتن ها قرار میدیم:
<%= s1[j] %>
<% j++; %>
در این کد یعنی: <% j++; %> ما نیازی نداریم که متغیر j دیده بشه و فقط می خواهیم که یکی بهش اضافه بشه پس از نوشتن کاراکتر = مثل کد ماقبلش جلوگیری می کنیم.
خب با این حرکته کمی عجیب ما تونستم کاری کنیم که هر سطری برای خودش یه متغیر داشته باشه
حالا می مونه این بحث که چطور به این اندیس ها مقدار بدیم.
باز هم اینجا مشکلی وجود داره و اون هم اینه که با انتخاب یک رادیو باتن چطور تشخیص داده بشه که از کدوم سطر رادیو باتن یک RadioButtonList انتخاب شده چون ما بیش از یه دونه RadioButtonList در سمت کلاینت داریم.
خب برای حل این مشکل از یه روش غیر معمول استفاده کردم و اومدم یک متغیر z تعریف کردم و اون رو داخل پروپرتی ToolTip هر یک از RadioButtonList ها به شکل زیر قرار دادم، تا بعد از مراجعه به این پروپرتی و استخراج اون متوجه بشیم که کدوم یکی از این RadioButtonList ها رویداد SelectedIndexChanged رو فراخوانی کرده
<asp:RadioButtonList ID="RadioButtonList1" runat="server" ToolTip="<%# (z++) %>"
OnSelectedIndexChanged="RadioButtonList1_SelectedI ndexChanged" AutoPostBack="True">
<asp:ListItem Value="1">first</asp:ListItem>
<asp:ListItem Value="2">second</asp:ListItem>
همینجور که می بینید توسط این دستور
ToolTip="<%# (z++) %>"
این پروپرتی رو مقدار دهی می کنیم.
نکته ریزی تویه این کد وجود داره که شاید بتویه در برنامه نویسی های بعدی شما، کمک حالتون بشه و اون عملگر ++ هست، این رو بصورت پسوندی استفاده کردم، نه بصورت پیشوندی
علتش هم ایته که اول مقدار جاری متغیر z رو به پروپرتی نسبت میده و بعد این متغیر رو افزایش میده که می تونه باعث بشه تا در صورت نیاز در سطرهای بعدی استفاده بشه
خب با متغیر z هر یک از RadioButtonList ها رو نشانه گذاری یا به عبارتی شماره گذاری کردیم.
حالا نوبت اینه متد رویداد OnSelectedIndexChanged رو کد نویسی کنیم.
قبل اینه که داخل این متد رو توضیح بدم باید به این نکته توجه کنیم که چه کسی این متد رو فراخوانی می کنه؟ چون همونطور که قبلا گفتم در سمت کلاینت هر سطر یک RadioButtonList برای خودش داره
این متد رویداد دارای دو پارامتر به نام های sender از نوع object و e از نوع EventArgs هست. شی sender نام کنترل رو در خودش داره و شی e هم رویدادی که رخ داده رو در خودش نگهداری می کنه.
حالا با این توضیح کد زیر رو توضیح میدم:
protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)
{
RadioButtonList r = (RadioButtonList)sender;
s1[int.Parse( r.ToolTip.Trim())] = "گزینه با موفقیت ثبت شد";
}
ما میدونیم که sender کنترلی از نوع RadioButtonList رو در خودش داره پس با این کد
RadioButtonList r = (RadioButtonList)sender;
تمام پروپرتی ها و مشخصات کنترل مورد نظر رو به شی r از نوع RadioButtonList انتقال میدیم.
شی r هم یه پروپرتی داره به نام ToolTip که قبلا با متغیر z مقدار دهیش کردیم. حالا توسط این کد
int.Parse( r.ToolTip.Trim())
شماره اندیسی رو که برای آرایه s1 نیاز داریم تا مقدار دهی بشه رو بدست میاریم و توسط کد زیر به این شکل مقدار دهی می کنیم:
s1[int.Parse( r.ToolTip.Trim())] = "گزینه با موفقیت ثبت شد";
چند نکته رو در انتها باید بگم:
- اگر خواستید متغیر رو درقسمت کد نویسی به صورتی تعریف کنید که داخل صفحه هم بشه فراخوانی کرد باید از کلیدی protected قبل از نوع متغیر استفاده کنید. مانند کد زیر
protected string[] s1 = new string[5];
- اگر خواستید از طریق کد نویسی یه زبان برنامه نویسی به پروپرتی یه کنترل مقدار بدید باید توسط این کد انجام بشه
<%# کد مورد نظر %>
یعنی از علامت # استفاده بشه مثل این کد:ToolTip="<%# (z++) %>"
- اگر خواستید مقداری رو از طریق کدنویسی مقدار متغیری رو بر روی صفحه نمایش بدید از علامت = استفاده کنید مثل این کد:
<%= s1[j] %>
- اگر خواستید فقط کدی اجرا بشه و نمی خواهید که جایی نمایش یا به چیزی از صفحه نسبت داده بشه بعد علامت % چیزی قرار ندید مثل کد زیر
<% j++; %>
شاید نشه به یه کنترل داخل گریدویو یا ریپیتر مقدار داد ولی مطمئنا میشه داخل این نوع کنترلر های دیتایی به یه متغیر مقدار داد.
همیشه راه برای دور زدن، محدودیت ها هست
اگه سوالی بود هستم در خدمتتون