দুর্ভাগ্যক্রমে এমন কোনও দুর্দান্ত এমভিভিএম উদাহরণ অ্যাপ নেই যা সমস্ত কিছু করে এবং কিছু করার জন্য বিভিন্ন রকম পন্থা রয়েছে। প্রথমত, আপনি সেখানে অ্যাপ্লিকেশন ফ্রেমওয়ার্কগুলির সাথে পরিচিত হতে চান (প্রিজম একটি শালীন পছন্দ), কারণ তারা আপনাকে নির্ভরযোগ্য ইনজেকশন, কমান্ডিং, ইভেন্টের সমষ্টি ইত্যাদির মতো সুবিধাজনক সরঞ্জামগুলি সহজেই আপনার উপযুক্ত অনুসারে বিভিন্ন ধরণের চেষ্টা করে দেখতে সরবরাহ করে because ।
প্রিজম রিলিজ:
http://www.codeplex.com/CompositeWPF
এতে অনেকগুলি ছোট উদাহরণ এবং কীভাবে করা যায় তার সাথে একটি দুর্দান্ত শালীন উদাহরণ অ্যাপ (স্টক ব্যবসায়ী) অন্তর্ভুক্ত রয়েছে। খুব কমপক্ষে এটি বেশ কয়েকটি সাধারণ উপ-নিদর্শনগুলির একটি ভাল বুদ্ধি যা এমভিভিএমকে বাস্তবে কাজ করতে ব্যবহার করে। সিআরইউডি এবং ডায়ালগ উভয়ের জন্যই তাদের উদাহরণ রয়েছে, আমি বিশ্বাস করি।
প্রিজম অগত্যা প্রতিটি প্রকল্পের জন্য নয়, তবে এটির সাথে পরিচিত হওয়া ভাল।
CRUD:
এই অংশটি বেশ সহজ, ডাব্লুপিএফ-এর দ্বিমুখী বাইন্ডিংগুলি বেশিরভাগ ডেটা সম্পাদনা করা সত্যই সহজ করে তুলেছে। আসল কৌশলটি এমন একটি মডেল সরবরাহ করা যা ইউআই সেটআপ করা সহজ করে। খুব কমপক্ষে আপনি এটি নিশ্চিত করতে চান যে আপনার ভিউমোডেল (বা ব্যবসায়িক অবজেক্ট) INotifyPropertyChanged
বাঁধাই সমর্থন করার জন্য প্রয়োগ করে এবং আপনি সম্পত্তিগুলি সরাসরি ইউআই নিয়ন্ত্রণগুলিতে আবদ্ধ করতে পারেন, তবে আপনি IDataErrorInfo
বৈধতার জন্যও প্রয়োগ করতে চাইতে পারেন । সাধারণত, আপনি যদি সিআরইউডি সেটআপ করার জন্য কোনও ধরণের ORM সমাধান ব্যবহার করেন তবে তা স্ন্যাপ।
এই নিবন্ধটি সাধারণ ক্রুড অপারেশনগুলি দেখায়:
http://dotnetslackers.com/articles/wpf/WPFDataBindingWithLINQ.aspx
এটি লিনকটোসকিএল-এ নির্মিত হয়েছে, তবে এটি উদাহরণের সাথে অপ্রাসঙ্গিক - গুরুত্বপূর্ণ যেটি আপনার ব্যবসায়ের অবজেক্টগুলি বাস্তবায়ন করে INotifyPropertyChanged
(লিনকটোসকিএল দ্বারা উত্পাদিত ক্লাসগুলি কী করে)। এমভিভিএম সেই উদাহরণটির মূল বিষয় নয়, তবে আমি মনে করি না যে এটি এই ক্ষেত্রে গুরুত্বপূর্ণ।
এই নিবন্ধটি ডেটা বৈধতা দেখায়
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-uthoration-in-3-5.aspx
আবার, বেশিরভাগ ORM সমাধানগুলি ক্লাস তৈরি করে যা ইতিমধ্যে প্রয়োগ করে IDataErrorInfo
এবং সাধারণত কাস্টম বৈধকরণের বিধিগুলি যুক্ত করা সহজ করার জন্য একটি প্রক্রিয়া সরবরাহ করে।
বেশিরভাগ সময় আপনি কোনও ওআরএম দ্বারা নির্মিত একটি বস্তু (মডেল) নিতে এবং এমন একটি ভিউমোডেলে মোড়ানো করতে পারেন যা এটি ধারণ করে এবং সংরক্ষণ / মোছার জন্য আদেশ দেয় - এবং আপনি ইউআইআই কে সরাসরি মডেলের বৈশিষ্ট্যে আবদ্ধ করতে প্রস্তুত।
ভিউটির মতো দেখতে কিছুটা (ভিউমোডেলের একটি সম্পত্তি Item
রয়েছে যা ওআরএম-তে তৈরি শ্রেণীর মতো মডেল ধারণ করে):
<StackPanel>
<StackPanel DataContext=Item>
<TextBox Text="{Binding FirstName, Mode=TwoWay, ValidatesOnDataErrors=True}" />
<TextBox Text="{Binding LastName, Mode=TwoWay, ValidatesOnDataErrors=True}" />
</StackPanel>
<Button Command="{Binding SaveCommand}" />
<Button Command="{Binding CancelCommand}" />
</StackPanel>
সংলাপ:
ডায়ালগ এবং এমভিভিএম কিছুটা জটিল। আমি সংলাপগুলির সাথে মধ্যস্থতার পদ্ধতির স্বাদ ব্যবহার করতে পছন্দ করি, আপনি স্ট্যাকওভারফ্লো প্রশ্নটিতে এটি সম্পর্কে আরও কিছুটা পড়তে পারেন: ডাব্লুপিএফ
এমভিভিএম ডায়ালগ উদাহরণ
আমার স্বাভাবিক পদ্ধতির, যা বেশিরভাগ ক্লাসিক এমভিভিএম নয়, এর সংক্ষিপ্ত বিবরণ দেওয়া যেতে পারে:
ডায়লগের ভিউমোডেলের একটি বেস ক্লাস যা কমান্ড ও বাতিল ক্রিয়াকলাপের আদেশগুলি উন্মোচিত করে, এমন একটি ইভেন্ট দর্শকদের জানতে দেয় যে একটি ডায়ালগ বন্ধ হতে প্রস্তুত এবং আপনার সমস্ত সংলাপে আপনার যা কিছু প্রয়োজন হবে।
আপনার কথোপকথনের জন্য একটি জেনেরিক দৃশ্য - এটি উইন্ডো বা একটি কাস্টম "মডেল" ওভারলে টাইপ নিয়ন্ত্রণ হতে পারে। এর অন্তরে এটি একটি সামগ্রী উপস্থাপক যা আমরা ভিউমোডেলটিকে এতে intoুকিয়ে দিয়েছি এবং এটি উইন্ডোটি বন্ধ করার জন্য তারগুলি পরিচালনা করে - উদাহরণস্বরূপ ডেটা প্রসঙ্গে পরিবর্তন আপনি পরীক্ষা করতে পারেন যে নতুন ভিউমোডেলটি আপনার বেস বর্গ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়েছে, এবং যদি তা হয় তবে সম্পর্কিত ঘনিষ্ঠ ইভেন্টটি সাবস্ক্রাইব করুন (হ্যান্ডলারটি ডায়ালগের ফলাফল নির্ধারণ করবে)। যদি আপনি বিকল্প সার্বজনীন ঘনিষ্ঠ কার্যকারিতা সরবরাহ করেন (উদাহরণস্বরূপ এক্স বোতাম), আপনার ভিউমোডেলে প্রাসঙ্গিক ক্লোজ কমান্ডটি চালানোও নিশ্চিত করা উচিত।
আপনার ভিউমোডেলগুলির জন্য আপনাকে কোথাও ডেটা টেম্পলেট সরবরাহ করতে হবে, এগুলি খুব সহজ হতে পারে বিশেষত যেহেতু আপনার সম্ভবত পৃথক নিয়ন্ত্রণে থাকা প্রতিটি ডায়ালগের জন্য একটি ভিউ রয়েছে। ভিউমোডেলের জন্য ডিফল্ট ডেটা টেমপ্লেট এর পরে এর মতো কিছু দেখাবে:
<DataTemplate DataType="{x:Type vmodels:AddressEditViewModel}">
<views:AddressEditView DataContext="{Binding}" />
</DataTemplate>
ডায়ালগ ভিউতে এগুলির অ্যাক্সেস থাকা দরকার, কারণ অন্যথায় এটি কীভাবে ভিউমডেলটি দেখানো হবে তা জানবে না, ভাগ করা ডায়ালগ ইউআই বাদে এর বিষয়বস্তুগুলি মূলত এটি:
<ContentControl Content="{Binding}" />
অন্তর্নিহিত ডেটা টেমপ্লেটটি মডেলটিতে দৃশ্যটি মানচিত্র করবে, তবে কে এটি চালু করবে?
এটি এমভিভিএম অংশ নয়। এটি করার একটি উপায় হ'ল একটি গ্লোবাল ইভেন্ট ব্যবহার করা। আমি যা করি তার থেকে ভাল কাজটি হ'ল নির্ভরতা ইনজেকশনের মাধ্যমে সরবরাহিত ইভেন্ট অগ্রিগেটর টাইপ সেটআপ ব্যবহার করা - এইভাবে ঘটনাটি পুরো অ্যাপ্লিকেশনটি নয়, একটি ধারক হিসাবে বিশ্বব্যাপী। প্রিজম ধারক শব্দার্থকতা এবং নির্ভরতা ইনজেকশনের জন্য unityক্য কাঠামো ব্যবহার করে এবং সামগ্রিকভাবে আমি ইউনিটিটিকে বেশ খানিকটা পছন্দ করি।
সাধারণত, মূল উইন্ডোটি এই ইভেন্টটির সদস্যতা নেওয়ার জন্য এটি অর্থবোধ করে - এটি ডায়ালগটি খুলতে পারে এবং ভিউমোডেলে এটির ডেটা প্রসঙ্গে সেট করতে পারে যা উত্থিত ইভেন্টের সাথে পাস হয়।
এই উপায়ে সেট আপ করুন ভিউমোডেলস অ্যাপ্লিকেশনটিকে একটি ডায়ালগ খোলার অনুরোধ জানাতে এবং সেখানে ইউআই সম্পর্কে কিছু না জেনে সেখানে ব্যবহারকারীর ক্রিয়াকে প্রতিক্রিয়া জানাতে যাতে বেশিরভাগ অংশের জন্য এমভিভিএম-নেস সম্পূর্ণ থাকে।
এমন অনেক সময় রয়েছে, যেখানে ইউআইকে ডায়লগগুলি বাড়িয়ে তুলতে হয় যা কিছুটা জটিল করে তোলে। উদাহরণস্বরূপ বিবেচনা করুন, যদি ডায়ালগের অবস্থানটি এটি খোলে যে বোতামটির অবস্থানের উপর নির্ভর করে। এই ক্ষেত্রে আপনার ডায়ালগ খোলার অনুরোধ করার সময় আপনার কিছু UI নির্দিষ্ট তথ্য থাকতে হবে। আমি সাধারণত একটি পৃথক শ্রেণি তৈরি করি যা একটি ভিউমোডেল এবং কিছু প্রাসঙ্গিক UI তথ্য ধারণ করে। দুর্ভাগ্যক্রমে কিছু সংযোগ সেখানে অপরিহার্য বলে মনে হচ্ছে।
একটি বোতাম হ্যান্ডলারের সিউডো কোড যা একটি ডায়ালগ উত্থাপন করে যা উপাদান অবস্থানের ডেটা প্রয়োজন:
ButtonClickHandler(sender, args){
var vm = DataContext as ISomeDialogProvider; // check for null
var ui_vm = new ViewModelContainer();
// assign margin, width, or anything else that your custom dialog might require
...
ui_vm.ViewModel = vm.SomeDialogViewModel; // or .GetSomeDialogViewModel()
// raise the dialog show event
}
ডায়ালগ ভিউটি ডেটা অবস্থানের সাথে আবদ্ধ করবে এবং অন্তর্ভুক্ত থাকা ভিডমোডেলটি প্রেরণ করবে ContentControl
। ভিউমোডেল নিজেই এখনও ইউআই সম্পর্কে কিছু জানে না।
সাধারণভাবে আমি পদ্ধতির DialogResult
ফেরতের সম্পত্তি ব্যবহার করি না ShowDialog()
বা ডায়ালগটি বন্ধ না হওয়া পর্যন্ত থ্রেডটি ব্লক হওয়ার আশা করি না। একটি অ-মানক মডেল ডায়ালগ সর্বদা এর মতো কাজ করে না এবং একটি যৌগিক পরিবেশে আপনি প্রায়শই কোনও ইভেন্ট হ্যান্ডলারটি কোনওভাবেই এটির মতো ব্লক করতে চান না। আমি ভিউমোডেলগুলি এটির সাথে চুক্তি করতে পছন্দ করি - একটি ভিউমোডেলের স্রষ্টা তার সম্পর্কিত ইভেন্টগুলিতে সাবস্ক্রাইব করতে পারেন, প্রতিশ্রুতিবদ্ধ / বাতিল পদ্ধতিগুলি সেট করতে পারেন, তাই এই ইউআই পদ্ধতিতে নির্ভর করার দরকার নেই।
সুতরাং পরিবর্তে এই প্রবাহ:
// in code behind
var result = somedialog.ShowDialog();
if (result == ...
আমি ব্যবহার করি:
// in view model
var vm = new SomeDialogViewModel(); // child view model
vm.CommitAction = delegate { this.DoSomething(vm); } // what happens on commit
vm.CancelAction = delegate { this.DoNothing(vm); } // what happens on cancel/close (optional)
// raise dialog request event on the container
আমি এটিকে এটিকে পছন্দ করি কারণ আমার বেশিরভাগ ডায়ালগগুলি সিউডো-মডেল নিয়ন্ত্রণগুলি অ-ব্লক করা এবং এটিকে এভাবে করা তার চারপাশে কাজ করার চেয়ে আরও সহজবোধ্য বলে মনে হয়। ইউনিট পরীক্ষার পাশাপাশি সহজ।