দ্রুত উত্তরটি হ'ল for()
আপনার foreach()
লুপগুলির স্থানে একটি লুপ ব্যবহার করা । কিছুটা এইরকম:
@for(var themeIndex = 0; themeIndex < Model.Theme.Count(); themeIndex++)
{
@Html.LabelFor(model => model.Theme[themeIndex])
@for(var productIndex=0; productIndex < Model.Theme[themeIndex].Products.Count(); productIndex++)
{
@Html.LabelFor(model=>model.Theme[themeIndex].Products[productIndex].name)
@for(var orderIndex=0; orderIndex < Model.Theme[themeIndex].Products[productIndex].Orders; orderIndex++)
{
@Html.TextBoxFor(model => model.Theme[themeIndex].Products[productIndex].Orders[orderIndex].Quantity)
@Html.TextAreaFor(model => model.Theme[themeIndex].Products[productIndex].Orders[orderIndex].Note)
@Html.EditorFor(model => model.Theme[themeIndex].Products[productIndex].Orders[orderIndex].DateRequestedDeliveryFor)
}
}
}
তবে কেন এটি সমস্যার সমাধান করে তা নিয়ে এই সমস্যাগুলি প্রকাশিত হয়।
এই সমস্যাটি সমাধান করার আগে আপনার কাছে তিনটি জিনিস রয়েছে যা কমপক্ষে একটি কারসারি বোঝা। আমাকে স্বীকার করতে হবে যে যখন আমি কাঠামোটি নিয়ে কাজ শুরু করি তখন আমি এটিকে দীর্ঘ সময়ের জন্য কার্গো-সিলেট করেছিলাম। যা ঘটছে তা পেতে পেতে আমার বেশ খানিকটা সময় লেগেছিল
এই তিনটি জিনিস হ'ল:
- এমভিসিতে কীভাবে
LabelFor
অন্যান্য ...For
সহকারীরা কাজ করবেন?
- একটি এক্সপ্রেশন ট্রি কি?
- মডেল বাইন্ডার কীভাবে কাজ করে?
এই ধারণাগুলির তিনটিই একটি উত্তর পেতে লিংক করেছে।
এমভিসিতে কীভাবে LabelFor
অন্যান্য ...For
সহকারীরা কাজ করবেন?
সুতরাং, আপনি ব্যবহার করেছি HtmlHelper<T>
জন্য এক্সটেনশন LabelFor
এবং TextBoxFor
এবং অন্যদের, এবং আপনি সম্ভবত লক্ষ্য করেছি যে, যখন আপনি তাদের ডাকা, আপনি তাদের একটি ল্যামডা পাস করে যেতে এবং জাদুর কিছু html জেনারেট করে। কিন্তু কিভাবে?
সুতরাং প্রথম জিনিসটি লক্ষ্য করার জন্য এই সাহায্যকারীদের স্বাক্ষর। এর জন্য সবচেয়ে সহজ ওভারলোডটি দেখে নেওয়া যাক
TextBoxFor
public static MvcHtmlString TextBoxFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression
)
প্রথমত, HtmlHelper
প্রকারের ধরণের টাইপের জন্য এটি একটি এক্সটেনশন পদ্ধতি <TModel>
। সুতরাং, পর্দার আড়ালে কী ঘটে তা কেবল সরলভাবে জানাতে, যখন রেজার এই দৃশ্যটিকে রেন্ডার করে এটি একটি বর্গ তৈরি করে। এই শ্রেণীর অভ্যন্তরে একটি উদাহরণ রয়েছে HtmlHelper<TModel>
(সম্পত্তি হিসাবে Html
, তাই আপনি ব্যবহার করতে পারেন @Html...
), যেখানে TModel
আপনার @model
বিবৃতিতে সংজ্ঞায়িত ধরণটি রয়েছে। সুতরাং আপনার ক্ষেত্রে, আপনি যখন এই দৃষ্টিভঙ্গিটি দেখছেন তখন TModel
সর্বদা ধরণের হবে ViewModels.MyViewModels.Theme
।
এখন, পরবর্তী যুক্তিটি কিছুটা জটিল। সুতরাং একটি অনুরোধ তাকান
@Html.TextBoxFor(model=>model.SomeProperty);
দেখে মনে হচ্ছে আমাদের কাছে কিছুটা ল্যাম্বদা রয়েছে, এবং যদি কেউ স্বাক্ষরটি অনুমান করে তবে কেউ ভাবতে পারে যে এই যুক্তির ধরণটি কেবল একটি হবে Func<TModel, TProperty>
, যেখানে TModel
ভিউ মডেলের TProperty
ধরণ রয়েছে এবং সম্পত্তিটির ধরণ হিসাবে অনুমান করা হয়।
তবে এটি বেশ সঠিক নয়, আপনি যদি যুক্তির আসল ধরণটি দেখেন তবে এর Expression<Func<TModel, TProperty>>
।
সুতরাং যখন আপনি সাধারণত একটি ল্যাম্বদা উত্পন্ন করেন, সংকলকটি লম্বাটি নিয়ে যায় এবং এমএসআইএল-তে এটি সংকলন করে, অন্য কোনও ফাংশনের মতো (যার কারণে আপনি প্রতিনিধি, পদ্ধতি গ্রুপ এবং ল্যাম্বডাস আরও বা কম বিনিময়যোগ্যভাবে ব্যবহার করতে পারেন, কারণ এগুলি কেবল কোডের উল্লেখ ।)
যাইহোক, সংকলকটি দেখতে পায় যে প্রকারটি একটি Expression<>
, এটি তাত্ক্ষণিকভাবে ল্যাম্বডাকে এমএসআইএলে সংকলন করে না, পরিবর্তে এটি একটি এক্সপ্রেশন ট্রি উত্পন্ন করে!
সুতরাং, হেক কি একটি অভিব্যক্তি গাছ। ঠিক আছে, এটি জটিল নয় তবে এটি পার্কে হাঁটাও নয়। এমএস উদ্ধৃত করতে:
| এক্সপ্রেশন ট্রি একটি গাছের মতো ডেটা স্ট্রাকচারে কোড উপস্থাপন করে যেখানে প্রতিটি নোড একটি এক্সপ্রেশন, উদাহরণস্বরূপ, কোনও পদ্ধতি কল বা বাইনারি অপারেশন যেমন x <y।
সোজা কথায়, একটি এক্সপ্রেশন ট্রি "ক্রিয়াকলাপ" এর সংগ্রহ হিসাবে কোনও ফাংশনের প্রতিনিধিত্ব।
এর ক্ষেত্রে model=>model.SomeProperty
, এক্সপ্রেশন ট্রিটির একটি নোড থাকবে যা বলে যে: "'মডেল' থেকে 'কিছু সম্পত্তি' পান"
এই এক্সপ্রেশন ট্রি একটি অনুরোধ করা যেতে পারে এমন একটি ফাংশন মধ্যে সংকলন করা যেতে পারে, তবে যতক্ষণ না এটি একটি এক্সপ্রেশন ট্রি, এটি কেবল নোডের সংগ্রহ।
সুতরাং কি জন্য ভাল?
সুতরাং Func<>
বা Action<>
, একবার আপনার কাছে এলে তারা বেশ পারমাণবিক। আপনি যা করতে পারেন তা হ'ল Invoke()
ওরফে তাদের যে কাজটি করার কথা বলেছে তা করতে বলুন।
Expression<Func<>>
অন্যদিকে, ক্রিয়াকলাপের একটি সংগ্রহ উপস্থাপন করে, যা সংযোজন, হেরফের করা, পরিদর্শন করা , বা সংকলন ও আহবান করা যেতে পারে।
তাহলে তুমি আমাকে এসব কেন বলছ?
সুতরাং একটি বুঝতে কি সঙ্গে Expression<>
, আমরা ফিরে যেতে পারেন Html.TextBoxFor
। এটি যখন একটি পাঠ্যবাক্স রেন্ডার করে, আপনি যে সম্পত্তিটি দিচ্ছেন সে সম্পর্কে কিছু জিনিস উত্পন্ন করা দরকার । ভীষণ পছন্দ attributes
যাচাইকরণের জন্য সম্পত্তি, এবং এই ক্ষেত্রে বিশেষভাবে এটা চিন্তা করার কি দরকার নাম<input>
ট্যাগ।
এটি এক্সপ্রেশন ট্রি "হাঁটা" এবং একটি নাম তৈরি করে এটি করে। সুতরাং যেমন একটি অভিব্যক্তি জন্য model=>model.SomeProperty
, এটি আপনি জিজ্ঞাসা করছেন এবং বিল্ড করা বৈশিষ্ট্য সংগ্রহ করে এক্সপ্রেশন হাঁটা <input name='SomeProperty'>
।
আরও জটিল উদাহরণের জন্য, যেমন model=>model.Foo.Bar.Baz.FooBar
এটি উত্পন্ন হতে পারে<input name="Foo.Bar.Baz.FooBar" value="[whatever FooBar is]" />
ধারণা তৈরী কর? এটি কেবল যে কাজটি করে Func<>
তা নয়, এটি কীভাবে এটি কাজ করে তা এখানে গুরুত্বপূর্ণ।
(লিনকু থেকে এসকিউএল এর মতো অন্যান্য কাঠামোগুলি নোট করুন যেমন একটি এক্সপ্রেশন ট্রিতে হাঁটতে এবং একটি ভিন্ন ব্যাকরণ তৈরি করে যেমন এই ক্ষেত্রে একটি এসকিউএল কোয়েরি করে)
মডেল বাইন্ডার কীভাবে কাজ করে?
সুতরাং একবার আপনি এটি পেতে, আমরা সংক্ষেপে মডেল বাইন্ডার সম্পর্কে কথা বলতে হবে। ফর্মটি পোস্ট হয়ে গেলে, এটি কেবল একটি ফ্ল্যাটের মতো
Dictionary<string, string>
, আমরা আমাদের নেস্টেড ভিউ মডেলটির যে স্তরক্রমিক কাঠামোটি পেয়েছি তা হারিয়ে ফেলেছি। এই কী-মান জুটির কম্বো নেওয়া এবং কিছু বৈশিষ্ট্য সহ কোনও বস্তুকে পুনরায় হাইড্রেট করার চেষ্টা করা মডেল বাইন্ডারের কাজ। এটা কিভাবে কাজ করে? আপনি "কী" বা পোস্ট হওয়া ইনপুটটির নাম ব্যবহার করে অনুমান করেছিলেন।
সুতরাং যদি ফর্ম পোস্ট মত লাগে
Foo.Bar.Baz.FooBar = Hello
এবং আপনি যাকে বলা মডেলটিতে পোস্ট করছেন SomeViewModel
, তারপরে এটি সহায়তাকারী প্রথম স্থানে যা করেছিল তার বিপরীত কাজ করে। এটি "ফু" নামে একটি সম্পত্তি অনুসন্ধান করে। তারপরে এটি "ফু" বন্ধ করে "বার" নামক একটি সম্পত্তি অনুসন্ধান করে, তারপরে এটি "বাজ" সন্ধান করে ... এবং আরও কিছু ...
অবশেষে এটি "FooBar" টাইপের মধ্যে মানটি বিশ্লেষণ করার চেষ্টা করে এবং এটি "FooBar" এ নির্ধারণ করে।
PHW !!!
এবং ভয়েলা, আপনি আপনার মডেল আছে। সবেমাত্র নির্মিত মডেল বাইন্ডারটি অনুরোধ করা অ্যাকশনে হস্তান্তরিত হয়।
সুতরাং আপনার সমাধান কাজ করে না কারণ Html.[Type]For()
সাহায্যকারীদের একটি অভিব্যক্তি প্রয়োজন। এবং আপনি কেবল তাদের একটি মান দিচ্ছেন। মানটির জন্য প্রসঙ্গটি কী তা এটির কোনও ধারণা নেই এবং এটি কী করতে হবে তা জানে না।
এখন কিছু লোক রেন্ডার করতে পার্টিয়ালগুলি ব্যবহারের পরামর্শ দিয়েছে। এখন এটি তাত্ত্বিকভাবে কাজ করবে, তবে সম্ভবত আপনি যেভাবে প্রত্যাশা করেছিলেন তা নয়। আপনি যখন আংশিক রেন্ডার করেন, আপনি প্রকারটি পরিবর্তন করছেন TModel
, কারণ আপনি অন্যরকম দৃশ্যের প্রসঙ্গে। এর অর্থ হ'ল আপনি নিজের সম্পত্তিটিকে একটি স্বল্প সংক্ষেপে বর্ণনা করতে পারবেন। এর অর্থ হ'ল সহায়ক যখন আপনার অভিব্যক্তির জন্য নাম উত্পন্ন করবে তখন তা অগভীর হবে। এটি কেবলমাত্র প্রদত্ত প্রকাশের ভিত্তিতে উত্পন্ন হবে (সম্পূর্ণ প্রসঙ্গ নয়)।
সুতরাং আসুন আমরা বলি যে আপনার একটি আংশিক রয়েছে যা "বাজ" রেন্ডার করেছে (আমাদের উদাহরণ থেকে আগে)। এই আংশিক ভিতরে আপনি কেবল বলতে পারেন:
@Html.TextBoxFor(model=>model.FooBar)
বরং
@Html.TextBoxFor(model=>model.Foo.Bar.Baz.FooBar)
তার মানে এটি এর মতো একটি ইনপুট ট্যাগ তৈরি করবে:
<input name="FooBar" />
কোনটি, যদি আপনি এই ফর্মটি এমন কোনও ক্রিয়াতে পোস্ট করছেন যা একটি বৃহত্তর গভীরভাবে নেস্ট করা ভিউমোডেলের প্রত্যাশা করে, তবে এটি FooBar
অফ অফ বলে সম্বলিত হাইড্রেট করার চেষ্টা করবে TModel
। যা সর্বোত্তম সেখানে নেই এবং সবচেয়ে খারাপটি সম্পূর্ণরূপে অন্যরকম। আপনি যদি কোনও নির্দিষ্ট ক্রিয়াতে পোস্ট করে Baz
যা রুট মডেলের পরিবর্তে কোনও গ্রহণ করে , তবে এটি দুর্দান্ত কাজ করবে! প্রকৃতপক্ষে, পার্টিয়ালগুলি আপনার দর্শন প্রসঙ্গে পরিবর্তন করার একটি ভাল উপায়, উদাহরণস্বরূপ যদি আপনার একাধিক ফর্মযুক্ত একটি পৃষ্ঠা থাকে যা সমস্ত ক্রিয়াকলাপে পোস্ট করে থাকে তবে প্রত্যেকটির জন্য একটি আংশিক রেন্ডারিং একটি দুর্দান্ত ধারণা হবে।
এখন আপনি যখন এই সমস্ত কিছু পেয়ে যান, আপনি Expression<>
ক্রমবর্ধমানভাবে সেগুলি প্রসারিত করে এবং তাদের সাথে অন্যান্য ঝরঝরে জিনিসগুলি সহ সত্যই আকর্ষণীয় জিনিসগুলি শুরু করতে পারেন । আমি এর কোনটিতে won'tুকব না। তবে, আশা করি, এটি আপনাকে পর্দার আড়ালে কী চলছে এবং কেন জিনিসগুলি সেভাবে আচরণ করছে সে সম্পর্কে আরও ভাল ধারণা দেবে।
@
সব আগে করা উচিত নয়foreach
? আপনারওHtml.EditorFor
(Html.EditorFor(m => m.Note)
যেমন, উদাহরণস্বরূপ) এবং অন্যান্য পদ্ধতিতে ল্যাম্বডাস থাকা উচিত নয় ? আমার ভুল হতে পারে তবে আপনি কি আপনার আসল কোডটি পেস্ট করতে পারবেন? আমি এমভিসিতে বেশ নতুন, তবে আপনি এটি আংশিক দর্শন বা সম্পাদকদের (যদি নাম হয় তবে?) দিয়ে এটি সহজেই সমাধান করতে পারেন।