أسب.نت:كيفية الوصول إلى عناصر إدخال النموذج التي تم إنشاؤها بواسطة المكرر؟

StackOverflow https://stackoverflow.com/questions/179938

  •  05-07-2019
  •  | 
  •  

سؤال

أرغب في إنشاء مكرر لمجموعة من مربعات الاختيار، على سبيل المثال:

<tr><td><input type="checkbox" name="t" value="11cbf4deb87" /> <input type="checkbox" name="a" value="33cbf4deb87" />stackoverflow.com</td></tr>
<tr><td><input type="checkbox" name="t" value="11cbf4deb88" /> <input type="checkbox" name="a" value="33cbf4deb87" />microsoft.com</td></tr>
<tr><td><input type="checkbox" name="t" value="11cd3f33a89" /> <input type="checkbox" name="a" value="33cbf4deb87" />gmail.com</td></tr>
<tr><td><input type="checkbox" name="t" value="1138fecd337" /> <input type="checkbox" name="a" value="33cbf4deb87" />youporn.com</td></tr>
<tr><td><input type="checkbox" name="t" value="11009efdacc" /> <input type="checkbox" name="a" value="33bf4deb87" />fantasti.cc</td></tr>

السؤال رقم 1:كيف يمكنني الإشارة بشكل فردي إلى كل مربع اختيار عند تشغيل المكرر حتى أتمكن من تعيين القيمة الفريدة؟

هل أقوم بربطها بالبيانات بشيء مثل:

<itemtemplate>
   <tr>
      <td>
         <input type="checkbox" name="t" 
            value="<%# ((Item)Container.DataItem).TangoUniquifier %>" />
         <input type="checkbox" name="a" 
            value="<%# ((Item)Container.DataItem).AlphaUniquifier %>" />
         <%# ((Item)Container.DataItem).SiteName %>
      </td>
   </tr>
</itemtemplate>

أو هل من المفترض أن أقوم بتعيينه بطريقة ما في OnItemDataBound؟

<asp:repeater id="ItemsRepeater" 
      OnItemDataBound="ItemsRepeater_OnItemDataBound" runat="server">
   ...
   <itemtemplate>
      <tr>
         <td>
            <input id="chkTango" type="checkbox" name="t" runat="server" />
            <input id="chkAlpha" type="checkbox" name="a" runat="server" />
            <%# ((Item)Container.DataItem).SiteName %>
         </td>
      </tr>
   </itemtemplate>
   ...
</asp:repeater>


protected void ItemsRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
   // if the data bound item is an item or alternating item (not the header etc)
   if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
   {
      // get the associated item
      Item item = (Item)e.Item.DataItem;

      //???
      this.chkTango.Value = item.TangoUniquifier;
      this.chkAlpha.Value = item.AlphaUniquifier;
   }
}

ولكن إذا كان من المفترض أن أشير إليه في الكود الخلفي، فكيف يمكنني الرجوع إليه في الكود الخلفي؟هل من المفترض أن أشير إليه باستخدام خاصية المعرف (من جانب الخادم) الخاصة بـ <INPUT> يتحكم؟أدرك أن معرف عنصر التحكم الموجود على جانب الخادم ليس هو نفس المعرف الذي سيكون موجودًا على العميل.

أو هل يجب علي أن أفعل شيئًا حيث يجب علي العثور على عنصر تحكم INPUT باسم "t" وآخر باسم "a"؟وما هو نوع التحكم في CheckBox الذي يسمح لي بتعيين قيمة الإدخال الخاصة به؟

protected void ItemsRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
   // if the data bound item is an item or alternating item (not the header etc)
   if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
   {
      // get the associated item
      Item item = (Item)e.Item.DataItem;

      CheckBox chkTango = (CheckBox)e.Item.FindControl("chkTango");
      chkTango.Value = item.TangoUniquifier;

      CheckBox chkAlpha = (CheckBox)e.Item.FindControl("chkAlpha");
      chkAlpha.Value = item.AlphaUniquifier;
   }
}

السؤال 2:عندما ينقر المستخدم لاحقًا على "إرسال"، كيف يمكنني العثور على جميع مربعات الاختيار المحددة، أو بشكل أكثر تحديدًا قيمها؟

هل يجب علي FindControl؟

protected void DoStuffWithLinks_Click(object sender, EventArgs e)
{
   // loop through the repeater items
   foreach (RepeaterItem repeaterItem in actionItemRepeater.Items)
   {
      Item item = repeaterItem.DataItem as Item;

      // grab the checkboxes
      CheckBox chkAlpha = (CheckBox)repeaterItem.FindControl("chkAlpha");
      CheckBox chkTango = (CheckBox)repeaterItem.FindControl("chkTango");

      if (chkAlpha.Checked)
      {          
         item.DoAlphaStuff(chkAlpha.Name);
      }

      if (chkTango.Checked)
      {
         item.DoTangoStuff(chkTango.Name);
      }
   }
}

هل لا تزال عناصر المكرر DataItem موجودة في معالج حدث النقر؟

هل كانت مفيدة؟

المحلول

استخدم عنصر تحكم الخادم بدلاً من إنشاء عنصر تحكم الإدخال runat=server

 <asp:CheckBox id="whatever" runat="Server" />

عندما تقوم بتعيين القيمة في ItemDataBound، فإنك تستخدم FindControl

CheckBox checkBox = (CheckBox)e.Item.FindControl("whatever");
checkBox.Checked = true;

عندما تحصل على العناصر، يمكنك أيضًا استخدام FindControl من العنصر الموجود في بنية foreach.وأيضًا، اعتمادًا على كيفية ربط البيانات، قد لا يكون DataItem موجودًا بعد إعادة النشر.

foreach (RepeaterItem item in myRepeater.Items)
{
    if (item.ItemType == ListItemType.Item 
        || item.ItemType == ListItemType.AlternatingItem) 
    { 
        CheckBox checkBox = (CheckBox)item.FindControl("whatever");
        if (checkBox.Checked)
        { /* do something */ }
    }
}
  • يميل العديد من الأشخاص إلى "الإرسال الآمن" باستخدام as عامل مع FindControl().لا يعجبني ذلك لأنه عند تغيير اسم عنصر التحكم في النموذج، يمكنك تجاهل خطأ التطوير بصمت مما يزيد من صعوبة تعقبه.أحاول استخدام فقط as المشغل إذا لم يكن التحكم مضمونًا هناك.

تحديث لـ: ما هو مربع الاختيار؟ في ملف HTML المعروض، سينتهي بك الأمر بالحصول على كل اسم مربع الاختيار هذا مثل

ctl00_cph0_ParentContainer_MyRepeater_ctl01_MyCheckbox
ctl00_cph0_ParentContainer_MyRepeater_ctl02_MyCheckbox
ctl00_cph0_ParentContainer_MyRepeater_ctl03_MyCheckbox

لا يهمك ما هي الأسماء لأن foreach item.FindControl()‎ يحصل عليها لك، ويجب ألا تفترض أي شيء عنها.ومع ذلك، عند التكرار عبر foreach، عادةً ما تحتاج إلى طريقة للإشارة إلى شيء ما.يتم ذلك في معظم الأحيان من خلال وجود عنصر تحكم asp:HiddenField بجانب كل CheckBox للاحتفاظ بمعرف لمطابقته احتياطيًا مع الكيان الصحيح.

مذكرة أمنية:هناك مشكلة أمنية تتعلق باستخدام الحقول المخفية لأنه يمكن تغيير الحقل المخفي في جافا سكريبت؛كن مدركًا دائمًا أنه كان من الممكن تعديل هذه القيمة بواسطة المستخدم قبل إرسال النموذج.

نصائح أخرى

وأنت قد تجد أنه من الأسهل استخدام عنصر تحكم CheckBoxList.

في حالة بسيطة، هل تعيين DataTextVield وDataValueField إلى اسم وقيمة كما سحبت من مصدر البيانات الخاص بك (على افتراض كنت ملء من مصدر بيانات) ومن ثم ربط ذلك لإنشاء العناصر.

وأقل ربما العمل على الجزء الخاص بك من خلق مربعات في مكرر.

وهنا بعض رمز معين لكيفية التعامل مع الحقل المخفي:

وتوصيف:

<asp:HiddenField ID="repeaterhidden" Value='<%# DataBinder.Eval(Container.DataItem, "value")%>' runat="server" >

وC #:

{

HiddenField hiddenField = (HiddenField)item.FindControl(repeaterStringhidden);

{ /* do something with hiddenField.Value */

و}

أعتقد أن قاعدة المعارف هذه أعطتني أفضل إجابة:

http://msdn.microsoft.com/en-us/library/1d04y8ss.aspx

ولقلة حظي، يبدو أن هذا متاح لإصدار .net 4.0 فقط (وما زلت عالقًا عند الإصدار 3.5 المزود بحزمة الخدمة SP1).

نقلا عن (الجريئة لي):

عندما يكون عنصر التحكم داخل عنصر تحكم مرتبط بالبيانات يقوم بإنشاء مثيلات متكررة لعنصر التحكم، يقوم ASP.NET بإنشاء قيم UniqueID وClientID لكل مثيل من السيطرة.يتم إنشاء قيمة UniqueID من خلال دمج قيمة UniqueID لحاوية التسمية وقيمة معرف عنصر التحكم ورقم تسلسلي.هذا هو الحال في عناصر التحكم مثل DataList، مكرر, وعناصر تحكم GridView وListView.

يقوم ASP.NET بإنشاء قيم ClientID بطريقة مشابهة عند تعيين خاصية ClientIDMode على AutoID.قد يؤدي ذلك إلى صعوبة الرجوع إلى عنصر التحكم في البرنامج النصي للعميل، لأنه لا يمكنك عادةً التنبؤ بقيم الأرقام التسلسلية المستخدمة.إذا كنت تريد الوصول إلى عناصر التحكم المرتبطة بالبيانات من البرنامج النصي للعميل، فيمكنك ذلك قم بتعيين الخاصية ClientIDMode إلى "متوقع". وهذا يجعل من السهل التنبؤ بقيم ClientID.

عندما تقوم بتعيين ClientIDMode على توقع، يمكنك ذلك قم أيضًا بتعيين الخاصية ClientIDRowSuffixDataKeys إلى اسم حقل البيانات الفريد, ، مثل المفتاح الأساسي في جدول قاعدة البيانات.يؤدي هذا إلى قيام ASP.NET بإنشاء معرف عميل سيكون من الأسهل التنبؤ به والإشارة إليه في البرنامج النصي للعميل إذا كان بإمكانك التنبؤ بقيم مفتاح البيانات.

لذلك، في الإصدار 3.5، أفعل ذلك باستخدام الحقول المخفية:

    foreach (RepeaterItem item in rptClientes.Items)
    {
        Panel pnl = (Panel)item.FindControl("divCliente");
        Control c = pnl.FindControl("hdnID");
        if (c is HiddenField)
        {
            if (((HiddenField)c).Value == hdnClienteNome.Value)
                pnl.BackColor = System.Drawing.Color.Beige;
        }
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top