ডব্লিউপিএফ-তে এমভিভিএম - মডেল পরিবর্তনের ভিউমোডেলকে কীভাবে সতর্ক করা যায় ... বা আমার উচিত?


112

আমি কয়েকটি এমভিভিএম নিবন্ধ দিয়ে যাচ্ছি, প্রাথমিকভাবে এটি এবং এটি

আমার সুনির্দিষ্ট প্রশ্নটি হল: আমি মডেল থেকে ভিউমোডলে পরিবর্তনগুলি কীভাবে যোগাযোগ করব?

জোশের নিবন্ধে, আমি দেখতে পাচ্ছি না যে তিনি এটি করেন। ভিউমোডেল সর্বদা বৈশিষ্ট্যগুলির জন্য মডেলকে জিজ্ঞাসা করে। রাহেলের উদাহরণে, তিনি মডেলটি বাস্তবায়ন করেছেন এবং মডেল INotifyPropertyChangedথেকে ঘটনা উত্থাপন করেছেন, তবে সেগুলি নিজেই দেখুন (সে কী করে সে সম্পর্কে আরও বিশদে তার নিবন্ধ / কোড দেখুন) consumption

কোথাও আমি এমন উদাহরণ দেখি না যেখানে মডেল বৈশিষ্ট্যগুলিতে পরিবর্তনগুলির ভিউমোডেলকে সতর্ক করে। এটি আমাকে চিন্তিত করেছে যে সম্ভবত এটি কোনও কারণে করা হয়নি। মডেল পরিবর্তনের ভিউমোডেলকে সতর্ক করার জন্য কি কোনও প্যাটার্ন রয়েছে? এটি অবশ্যই প্রয়োজনীয় বলে মনে হবে (১) অনুমিতভাবে প্রতিটি মডেলের জন্য ১ টিরও বেশি ভিউমোডেল রয়েছে এবং (২) এমনকি একটি ভিউমোডেল থাকলেও, মডেলটিতে কিছু পদক্ষেপের ফলে অন্যান্য বৈশিষ্ট্য পরিবর্তিত হতে পারে।

আমি সন্দেহ করি যে ফর্মটির উত্তর / মন্তব্য থাকতে পারে "আপনি কেন এটি করতে চান?" মন্তব্য, তাই এখানে আমার প্রোগ্রাম একটি বিবরণ। আমি এমভিভিএম-তে নতুন তাই সম্ভবত আমার পুরো নকশাটি ত্রুটিযুক্ত। আমি সংক্ষেপে এটি বর্ণনা করব।

আমি "গ্রাহক" বা "পণ্য" শ্রেণীর চেয়ে আরও আকর্ষণীয় (কমপক্ষে, আমার কাছে!) এমন কিছু প্রোগ্রাম করছি। আমি ব্ল্যাকজ্যাক প্রোগ্রাম করছি।

আমার একটি দৃষ্টিভঙ্গি রয়েছে যার পিছনে কোনও কোড নেই এবং কেবল ভিউমোডেলে (জোশ স্মিথের নিবন্ধটি দেখুন) বৈশিষ্ট্য এবং কমান্ডের সাথে আবদ্ধ হওয়ার উপর নির্ভর করে।

আরও ভাল বা খারাপ হওয়ার জন্য, আমি এমন মনোভাব নিয়েছি যে মডেলটিতে কেবল যেমন ক্লাসগুলিই নয় PlayingCard, পুরো ক্লাসটি স্থিত করে রাখে এমন ক্লাসও থাকতে হবে এবং যখন খেলোয়াড়টি Deckবাজে BlackJackGameগেছে তখন জানে, ডিলারকে কার্ড আঁকতে হবে এবং প্লেয়ার এবং ডিলারের বর্তমান স্কোরটি কী (21, 21, বুস্ট ইত্যাদির চেয়ে কম)।

থেকে BlackJackGameআমি "DrawCard" মত পদ্ধতি এক্সপোজ এবং এটা আমার ঘটেছে যে একটি কার্ড ড্র যখন হয়, যেমন বৈশিষ্ট্য CardScore, এবং IsBustআপডেট করা উচিত এবং এই নতুন মান ViewModel আদানপ্রদান। সম্ভবত এটি ত্রুটিপূর্ণ চিন্তাভাবনা?

কেউ ভিউমোডেল DrawCard()পদ্ধতিটি বলেছিল এমন মনোভাব গ্রহণ করতে পারে তাই তার আপডেট স্কোর জিজ্ঞাসা করতে হবে এবং সে আবক্ষু কিনা তা খুঁজে বের করতে হবে। মতামত?

আমার ভিউমোডেলে, আমার কাছে প্লেিং কার্ডের একটি আসল চিত্রটি (স্যুট, র‌্যাঙ্কের উপর ভিত্তি করে) দখল করার এবং এটিকে দেখার জন্য উপলব্ধ করার যুক্তি রয়েছে। মডেলটির সাথে এটি উদ্বিগ্ন হওয়া উচিত নয় (সম্ভবত অন্যান্য ভিউমোডেল কার্ডের চিত্রগুলি খেলার পরিবর্তে কেবল সংখ্যাগুলি ব্যবহার করবে)। অবশ্যই, কেউ কেউ আমাকে বলবেন যে মডেলটির এমনকি ব্ল্যাকজ্যাক গেমটির ধারণাগুলিও থাকা উচিত নয় এবং এটি ভিউমোডেলে পরিচালনা করা উচিত?


3
আপনি যে মিথস্ক্রিয়াটি শব্দগুলির বর্ণনা দিচ্ছেন এটি একটি স্ট্যান্ডার্ড ইভেন্ট মেকানিজমের মতো all মডেল নামক কোনও ইভেন্ট প্রকাশ করতে পারে OnBustএবং ভিএম এতে সদস্যতা নিতে পারে। আমার ধারণা আপনি পাশাপাশি আইএএ পদ্ধতির ব্যবহার করতে পারেন।
Live

আমি সত্যবাদী হব, যদি আমি সত্যিকারের ব্ল্যাকজ্যাক 'অ্যাপ' তৈরি করি তবে আমার তথ্য পরিষেবা / প্রক্সিগুলির কয়েকটি স্তর এবং এ + বি = সি এর মতো ইউনিট-পরীক্ষার একটি প্যাড্যান্টিক স্তরের আড়ালে থাকবে It এটি প্রক্সি হবে / পরিষেবা যা পরিবর্তনকে অবহিত করে।
মেরিওন হিউজেস

1
সবাইকে ধন্যবাদ! দুর্ভাগ্যক্রমে, আমি কেবল একটি উত্তর বেছে নিতে পারি। অতিরিক্ত স্থাপত্য পরামর্শের কারণে এবং আসল প্রশ্নটি পরিষ্কার করার কারণে আমি রাহেলকে বেছে নিচ্ছি। তবে প্রচুর দুর্দান্ত উত্তর ছিল এবং আমি তাদের প্রশংসা করি। -ড্যাভ
ডেভ


2
এফডাব্লুআইডাব্লু: প্রতি ডোমেন ধারণায় ভিএম এবং এম উভয় বজায় রাখার জটিলতা নিয়ে বেশ কয়েক বছর ধরে লড়াই করার পরে, আমি এখন বিশ্বাস করি যে উভয়কেই ডিআরওয়াই ব্যর্থ করে; উদ্বেগগুলির প্রয়োজনীয় বিভাজনটি একটি একক বস্তুর উপর দুটি ইন্টারফ্যাক্স - একটি "ডোমেন ইন্টারফেস" এবং "ভিউমোডেল ইন্টারফেস" রেখে আরও সহজেই করা যায়। এই অবজেক্টটি বিভ্রান্তি বা সিঙ্ক্রোনাইজেশনের অভাব ছাড়াই ব্যবসায়িক যুক্তি এবং দেখুন যুক্তি উভয়কেই দেওয়া যেতে পারে। এই অবজেক্টটি একটি "আইডেন্টিটি অবজেক্ট" - এটি স্বতন্ত্রভাবে সত্তাকে উপস্থাপন করে। ডোমেন কোড বনাম ভিউ কোডের বিচ্ছিন্নতা বজায় রাখার জন্য ক্লাসের মধ্যে এমন করার জন্য আরও ভাল সরঞ্জামের প্রয়োজন।
নির্মাতা স্টিভ

উত্তর:


61

আপনি যদি চান যে আপনার মডেলগুলি পরিবর্তনগুলির ভিউমোডেলগুলিকে সতর্ক করতে চান, তাদের উচিত আইএনটিফাইপ্রোপার্টিচেন্জড প্রয়োগ করা উচিত , এবং ভিউমোডেলগুলি প্রপার্টি চেঞ্জ বিজ্ঞপ্তিগুলি পেতে সাবস্ক্রাইব করা উচিত।

আপনার কোডটি এর মতো দেখতে পারে:

// Attach EventHandler
PlayerModel.PropertyChanged += PlayerModel_PropertyChanged;

...

// When property gets changed in the Model, raise the PropertyChanged 
// event of the ViewModel copy of the property
PlayerModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "SomeProperty")
        RaisePropertyChanged("ViewModelCopyOfSomeProperty");
}

তবে সাধারণত এটি তখনই প্রয়োজন হয় যদি একাধিক বস্তু মডেলের ডেটাতে পরিবর্তন করে চলেছে, যা সাধারণত হয় না।

আপনার যদি কখনও কখনও এমন ঘটনা ঘটে থাকে যেখানে প্রপার্টি চেঞ্জড ইভেন্টটি সংযুক্ত করার জন্য আপনার কাছে আপনার মডেল সম্পত্তির উল্লেখ নেই তবে আপনি প্রিজম EventAggregatorবা এমভিভিএম লাইটের মতো কোনও মেসেজিং সিস্টেম ব্যবহার করতে পারেন Messenger

আমার ব্লগে আমার মেসেজিং সিস্টেমগুলির একটি সংক্ষিপ্ত বিবরণ রয়েছে , তবে সংক্ষিপ্তসার হিসাবে, যে কোনও বস্তু কোনও বার্তা সম্প্রচার করতে পারে এবং যে কোনও বস্তু নির্দিষ্ট বার্তা শোনার জন্য সাবস্ক্রাইব করতে পারে। সুতরাং আপনি PlayerScoreHasChangedMessageকোনও অবজেক্ট থেকে কোনও সম্প্রচার করতে পারেন এবং অন্য কোনও অবজেক্ট সেই ধরণের বার্তা শোনার জন্য সাবস্ক্রাইব করতে পারে এবং PlayerScoreএটি শুনলেই তার সম্পত্তি আপডেট করতে পারে।

তবে আমি মনে করি না যে আপনার বর্ণিত সিস্টেমটির জন্য এটি প্রয়োজন।

একটি আদর্শ এমভিভিএম বিশ্বে আপনার অ্যাপ্লিকেশনটি আপনার ভিউমোডেলগুলি নিয়ে গঠিত এবং আপনার অ্যাপ্লিকেশনগুলি তৈরি করতে আপনার মডেলগুলি কেবলমাত্র ব্লক হিসাবে ব্যবহৃত। DrawCard()এগুলিতে সাধারণত কেবল ডেটা থাকে, সুতরাং এর মতো পদ্ধতিগুলি নেই (যা কোনও ভিউমোডেলে থাকবে)

সুতরাং আপনার সম্ভবত সম্ভবত এর মতো সরল মডেল ডেটা অবজেক্টগুলি থাকতে পারে:

class CardModel
{
    int Score;
    SuitEnum Suit;
    CardEnum CardValue;
}

class PlayerModel 
{
    ObservableCollection<Card> FaceUpCards;
    ObservableCollection<Card> FaceDownCards;
    int CurrentScore;

    bool IsBust
    {
        get
        {
            return Score > 21;
        }
    }
}

এবং আপনার মত একটি ভিউমোডেল অবজেক্ট থাকবে

public class GameViewModel
{
    ObservableCollection<CardModel> Deck;
    PlayerModel Dealer;
    PlayerModel Player;

    ICommand DrawCardCommand;

    void DrawCard(Player currentPlayer)
    {
        var nextCard = Deck.First();
        currentPlayer.FaceUpCards.Add(nextCard);

        if (currentPlayer.IsBust)
            // Process next player turn

        Deck.Remove(nextCard);
    }
}

(উপরের বিষয়গুলির সমস্ত প্রয়োগ করা উচিত INotifyPropertyChanged, তবে আমি এটিকে সরলতার জন্য ছেড়ে দিয়েছি)


3
আরও সাধারণভাবে, সমস্ত ব্যবসায়িক যুক্তি / নিয়মগুলি কি মডেলটিতে যায়? আপনি যেখানে 21 টি পর্যন্ত কার্ড নিতে পারেন তা বলে সমস্ত যুক্তি কোথায় যায় (তবে ডিলার 17 টিতে থাকে) যে আপনি কার্ডগুলি বিভক্ত করতে পারেন ইত্যাদি I আমি ধরে নিলাম এটি সমস্ত মডেল শ্রেণীর অন্তর্গত এবং সেই কারণেই আমি অনুভব করেছি যে আমার প্রয়োজন আছে মডেলটিতে একটি ব্ল্যাকজ্যাকগেম নিয়ামক শ্রেণি। আমি এখনও এটি বোঝার চেষ্টা করছি এবং উদাহরণ / উল্লেখগুলি প্রশংসা করব। আইওএস প্রোগ্রামিংয়ের আইটিউনস ক্লাস থেকে উদাহরণস্বরূপ ব্ল্যাকজ্যাকের ধারণাটি তোলা হয়েছিল যেখানে এমভিসি প্যাটার্নের মডেল ক্লাসে ব্যবসায়ের যুক্তি / নিয়ম অবশ্যই রয়েছে।
ডেভ

3
@ ডেভ হ্যাঁ, DrawCard()পদ্ধতিটি আপনার অন্যান্য গেম যুক্তি সহ ভিউমোডেলে থাকবে। একটি আদর্শ এমভিভিএম অ্যাপ্লিকেশনটিতে, আপনি কেবলমাত্র ভিউমোডেলগুলি তৈরি করে এবং সেগুলির পদ্ধতিগুলি যেমন একটি পরীক্ষা স্ক্রিপ্ট বা কমান্ড প্রম্পট উইন্ডোর মাধ্যমে চালনা করে পুরোপুরি ইউআই ছাড়াই আপনার অ্যাপ্লিকেশনটি চালাতে সক্ষম হবেন। মডেলগুলি কেবলমাত্র কাঁচা ডেটা এবং বেসিক ডেটা বৈধতাযুক্ত ডেটা মডেল।
রাহেল

6
সমস্ত সহায়তার জন্য র্যাচেল ধন্যবাদ। আমাকে আরও কিছু গবেষণা করতে হবে বা অন্য একটি প্রশ্ন লিখতে হবে; গেম যুক্তির অবস্থান সম্পর্কে আমি এখনও বিভ্রান্ত। আপনি (এবং অন্যরা) এটিকে ভিউমোডেলে রাখার পক্ষে ছিলেন, অন্যরা "ব্যবসায়িক যুক্তি" বলেছিলেন যা আমার ক্ষেত্রে আমি গেমের নিয়ম এবং গেমের অবস্থা মডেলটির অন্তর্ভুক্ত বলে মনে করি (উদাহরণস্বরূপ: এমএসডিএন.মাইক্রোসফটকম / en-us /library/gg405484%28v=pandp.40%29.aspx ) এবং stackoverflow.com/questions/10964003/... )। আমি বুঝতে পারি যে এই সাধারণ খেলায় এটি সম্ভবত খুব বেশি কিছু আসে না। তবে জেনে ভালো লাগবে। Thxs!
ডেভ

1
@ ডেভ আমি ভুলভাবে "ব্যবসায়িক যুক্তি" শব্দটি ব্যবহার করছি এবং এটিকে অ্যাপ্লিকেশন যুক্তির সাথে মিশিয়ে দিচ্ছি। এমএসডিএন নিবন্ধটি উদ্ধৃত করার জন্য আপনি "পুনরায় ব্যবহারের সুযোগগুলি সর্বাধিকীকরণের জন্য, মডেলগুলিতে কোনও ব্যবহারের ক্ষেত্রে নির্দিষ্ট হওয়া উচিত নয় task নির্দিষ্ট বা ব্যবহারকারীর কাজ application নির্দিষ্ট আচরণ বা অ্যাপ্লিকেশন যুক্তি" এবং "সাধারণত, ভিউ মডেলটি নির্দেশিত হতে পারে এমন আদেশগুলি বা ক্রিয়া সংজ্ঞায়িত করবে ইউআইতে এবং ব্যবহারকারী "অনুরোধ করতে পারে" । এর মতো জিনিসগুলি DrawCardCommand()ভিউমোডেলে থাকতে পারে তবে আমি অনুমান করি যে আপনি এমন একটি BlackjackGameModelবস্তু থাকতে পারেন যা একটি DrawCard()পদ্ধতি থাকতে পারে যা আপনি চাইলে আদেশটি বলেছিল
রাচেল

2
স্মৃতি ফুটো এড়িয়ে চলুন। একটি WeEEEvent প্যাটার্ন ব্যবহার করুন। joshsmithonwpf.wordpress.com/2009/07/11/…
জেজেএস

24

সংক্ষিপ্ত উত্তর: এটি নির্দিষ্টকরণের উপর নির্ভর করে।

আপনার উদাহরণে মডেলগুলি "তাদের নিজস্বভাবে" আপডেট করা হচ্ছে এবং অবশ্যই এই পরিবর্তনগুলি কোনওরকম দৃশ্যে প্রচার করতে হবে need যেহেতু দর্শনগুলি কেবলমাত্র ভিউ মডেলগুলিতে সরাসরি অ্যাক্সেস করতে পারে তাই এর অর্থ হল মডেলটিকে অবশ্যই এই পরিবর্তনগুলি সংশ্লিষ্ট ভিউমডেলের সাথে যোগাযোগ করতে হবে। এটি করার জন্য প্রতিষ্ঠিত প্রক্রিয়াটি অবশ্যই INotifyPropertyChanged, যার অর্থ আপনি এই জাতীয় একটি ওয়ার্কফ্লো পাবেন:

  1. ভিউমডেল তৈরি করা হয় এবং মডেল মোড়কে দেয়
  2. ভিউমডেল মডেলটির PropertyChangedইভেন্টটিতে সদস্যতা নিয়েছে
  3. ভিউমডেলটি ভিউ হিসাবে সেট করা থাকে DataContext, বৈশিষ্ট্যগুলি আবদ্ধ হয় ইত্যাদি
  4. ভিউ মডেলটিতে ক্রিয়াকলাপটি দেখুন
  5. মডেলটিতে ভিউমডেল কল পদ্ধতি
  6. মডেল নিজে আপডেট হয়
  7. ভিউমডেল মডেলগুলি পরিচালনা PropertyChangedকরে PropertyChangedএবং প্রতিক্রিয়াতে এটি নিজস্ব উত্থাপন করে
  8. প্রতিক্রিয়া লুপটি বন্ধ করে দেখুন, এর বাইন্ডিংগুলির পরিবর্তনগুলি প্রতিফলিত করে

অন্যদিকে যদি আপনার মডেলগুলিতে ব্যবসায়ের যুক্তি খুব সামান্য (বা না) থাকে, বা অন্য কোনও কারণে (যেমন লেনদেনের সক্ষমতা অর্জন করা) আপনি প্রতিটি ভিউমোডেলকে তার মোড়ানো মডেলটিকে "নিজস্ব" করতে দেওয়ার সিদ্ধান্ত নিয়েছেন তবে মডেলের সমস্ত পরিবর্তনগুলি মধ্য দিয়ে যেতে হবে ভিউ মডেল সুতরাং এই জাতীয় ব্যবস্থা প্রয়োজন হবে না।

আমি এখানে অন্য এমভিভিএম প্রশ্নের মধ্যে যেমন একটি নকশা বর্ণনা করি ।


হ্যালো, আপনি যে তালিকাটি করেছেন তা উজ্জ্বল। তবে আমার 7. এবং 8 এর সাথে সমস্যা আছে particular বিশেষত: আমার কাছে একটি ভিউমোডেল রয়েছে, যা INotifyPropertyChanged প্রয়োগ করে না। এতে বাচ্চাদের একটি তালিকা রয়েছে, এতে বাচ্চাদের একটি তালিকা রয়েছে (এটি ডাব্লুপিএফ ট্রিভিউ নিয়ন্ত্রণের জন্য ভিউমোডেল হিসাবে ব্যবহৃত হয়)। আমি কীভাবে ব্যবহারকারীর নিয়ন্ত্রণ ডেটা কনটেক্সট ভিউমোডেলকে কোনওরকমের (ট্র্রিভিউ আইটেমস) সম্পত্তি-পরিবর্তনগুলি "শ্রবণ" করব? আমি কীভাবে সমস্ত শিশু-উপাদানগুলির সাবস্ক্রাইব করব, যারা INotifyPropertyChanged প্রয়োগ করে? নাকি আমার আলাদা প্রশ্ন করা উচিত?
ইগোর

4

আপনার পছন্দগুলি:

  • INotifyPropertyChanged প্রয়োগ করুন
  • ঘটনাবলী
  • প্রক্সি ম্যানিপুলেটার সহ পোকো

আমি এটি দেখতে হিসাবে INotifyPropertyChanged। নেট একটি মৌলিক অংশ। অর্থাত্ এর ভিতরেSystem.dll । আপনার "মডেল" এ এটি প্রয়োগ করা ইভেন্ট স্ট্রাকচার বাস্তবায়নের অনুরূপ।

আপনি যদি খাঁটি পোকো চান, তবে আপনাকে কার্যকরভাবে প্রক্সি / পরিষেবাদির মাধ্যমে আপনার অবজেক্টগুলিকে ম্যানিপুলেট করতে হবে এবং তারপরে আপনার ভিউমোডেলকে প্রক্সি শোনার মাধ্যমে পরিবর্তনের বিষয়ে অবহিত করা হবে।

ব্যক্তিগতভাবে আমি INotifyPropertyChanged আলগাভাবে প্রয়োগ করি এবং তারপরে FODY ব্যবহার করি আমার জন্য নোংরা কাজ । এটি পোকো দেখতে এবং অনুভব করে।

একটি উদাহরণ (FODY থেকে IL ওয়েভ প্রোপার্টি চেঞ্জড রেইজারদের ব্যবহার করে):

public class NearlyPOCO: INotifyPropertyChanged
{
     public string ValueA {get;set;}
     public string ValueB {get;set;}

     public event PropertyChangedEventHandler PropertyChanged;
}

তারপরে আপনি আপনার ভিউমোডেলটি যে কোনও পরিবর্তনের জন্য প্রপার্টি চেঞ্জ করতে পারেন; বা সম্পত্তি নির্দিষ্ট পরিবর্তন।

INotifyPropertyChanged রুটের সৌন্দর্য, আপনি কি এটি একটি বর্ধিত পর্যবেক্ষণযোগ্য সংগ্রহের সাথে শৃঙ্খলাবদ্ধ করছেন? । সুতরাং আপনি আপনার নিকটস্থ পোকো অবজেক্টগুলিকে সংগ্রহের মধ্যে ফেলে দিন এবং সংগ্রহটি শুনুন ... যদি কোনও কিছু পরিবর্তন হয় তবে কোথাও, আপনি এটি সম্পর্কে শিখুন।

আমি সত্যবাদী হবো, এটি "আইএনটিফাইপ্রোপার্টিচেনজড স্বয়ংক্রিয়ভাবে সংকলক দ্বারা পরিচালিত হয়নি কেন" আলোচনায় যোগ দিতে পারে, যা রূপান্তরিত হয়: সি # এর প্রতিটি বস্তুর কোনও অংশ পরিবর্তন করা হয়েছে কিনা তা অবহিত করার সুবিধা থাকতে হবে; অর্থাৎ ডিফল্টরূপে INotifyPropertyChanged প্রয়োগ করুন। তবে এটি না এবং সর্বোত্তম রুট, যার জন্য সর্বনিম্ন পরিশ্রমের প্রয়োজন হয়, তা হল আইএল বয়ন (বিশেষত FODY ) ব্যবহার করা।


4

মোটামুটি পুরানো থ্রেড তবে অনেকগুলি অনুসন্ধানের পরে আমি আমার নিজস্ব সমাধানটি নিয়ে এসেছি: একটি প্রপার্টি চেঞ্জডপ্রক্সি

এই শ্রেণীর সাহায্যে আপনি সহজেই অন্য কারওর নোটিফাইপ্রোপার্টি চেঞ্জড রেজিস্ট্রেশন করতে পারেন এবং নিবন্ধিত সম্পত্তির জন্য বরখাস্ত করা হলে উপযুক্ত পদক্ষেপ নিতে পারেন।

এটির মতো দেখতে কেমন হতে পারে তার একটি নমুনা এখানে যখন আপনার কাছে একটি মডেল সম্পত্তি "স্ট্যাটাস" থাকে যা এটি নিজেই পরিবর্তিত হতে পারে এবং তারপরে ভিউমোডেলটিকে স্বয়ংক্রিয়ভাবে তার নিজস্ব স্থিতি পরিবর্তন করতে হবে যাতে এটি তার "স্থিতি" সম্পত্তিতে পরিবর্তন করে যাতে দৃশ্যটিও অবহিত হয়: )

public class MyModel : INotifyPropertyChanged
{
    private string _status;
    public string Status
    {
        get { return _status; }
        set { _status = value; OnPropertyChanged(); }
    }

    // Default INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class MyViewModel : INotifyPropertyChanged
{
    public string Status
    {
        get { return _model.Status; }
    }

    private PropertyChangedProxy<MyModel, string> _statusPropertyChangedProxy;
    private MyModel _model;
    public MyViewModel(MyModel model)
    {
        _model = model;
        _statusPropertyChangedProxy = new PropertyChangedProxy<MyModel, string>(
            _model, myModel => myModel.Status, s => OnPropertyChanged("Status")
        );
    }

    // Default INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

এবং এখানে নিজেই ক্লাস:

/// <summary>
/// Proxy class to easily take actions when a specific property in the "source" changed
/// </summary>
/// Last updated: 20.01.2015
/// <typeparam name="TSource">Type of the source</typeparam>
/// <typeparam name="TPropType">Type of the property</typeparam>
public class PropertyChangedProxy<TSource, TPropType> where TSource : INotifyPropertyChanged
{
    private readonly Func<TSource, TPropType> _getValueFunc;
    private readonly TSource _source;
    private readonly Action<TPropType> _onPropertyChanged;
    private readonly string _modelPropertyname;

    /// <summary>
    /// Constructor for a property changed proxy
    /// </summary>
    /// <param name="source">The source object to listen for property changes</param>
    /// <param name="selectorExpression">Expression to the property of the source</param>
    /// <param name="onPropertyChanged">Action to take when a property changed was fired</param>
    public PropertyChangedProxy(TSource source, Expression<Func<TSource, TPropType>> selectorExpression, Action<TPropType> onPropertyChanged)
    {
        _source = source;
        _onPropertyChanged = onPropertyChanged;
        // Property "getter" to get the value
        _getValueFunc = selectorExpression.Compile();
        // Name of the property
        var body = (MemberExpression)selectorExpression.Body;
        _modelPropertyname = body.Member.Name;
        // Changed event
        _source.PropertyChanged += SourcePropertyChanged;
    }

    private void SourcePropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == _modelPropertyname)
        {
            _onPropertyChanged(_getValueFunc(_source));
        }
    }
}

1
স্মৃতি ফুটো এড়িয়ে চলুন। একটি WeEEEvent প্যাটার্ন ব্যবহার করুন। joshsmithonwpf.wordpress.com/2009/07/11/…
জেজেএস

1
@ জেজেএস - ওটিওএইচ, দুর্বল ইভেন্টের প্যাটার্নটি বিপজ্জনক বলে বিবেচনা করুন । ব্যক্তিগতভাবে আমি বরং (আমি -= my_event_handler) নিবন্ধভুক্ত করতে ভুলে গেলে মেমরি ফাঁস হওয়ার ঝুঁকি নিয়ে থাকি , কারণ এমনটি বিরল + অবিশ্বাস্য জম্বি সমস্যার চেয়ে ট্র্যাক করা সহজ যা কখনও-না-হতে পারে।
টুলমেকারস্টেভ

@ টুলমেকারস্টেভ ভারসাম্যপূর্ণ যুক্তি যুক্ত করার জন্য ধন্যবাদ। আমি পরামর্শ দিচ্ছি যে বিকাশকারীরা তাদের নিজের পরিস্থিতিতে নিজের জন্য সর্বোত্তম কাজ করুন। অন্ধভাবে ইন্টারনেট থেকে উত্স কোড গ্রহণ করবেন না। অন্যান্য প্যাটার্ন রয়েছে যেমন ইভেন্টএগ্রিগেটর / ইভেন্টবাস সাধারণত ব্যবহৃত ক্রস-উপাদান মেসেজিং (যা তাদের নিজস্ব বিপদগুলি দ্বারাও তৈরি হয়)
জেজেএস

2

আমি এই নিবন্ধটি সহায়ক বলে মনে করেছি: http://social.msdn.microsoft.com/ Forums / vstudio / en-US / 3eb70678-c216-414f-a4a5-e1e3e557bb95 / mvvm-businesslogic-is-part- of- the-?forum = wpf

আমার সংক্ষিপ্তসার:

এমভিভিএম সংস্থার পিছনে ধারণাটি হল ভিউ এবং মডেলগুলির পুনরায় ব্যবহারের অনুমতি দেওয়া এবং ডিকপলড পরীক্ষার অনুমতি দেওয়া। আপনার ভিউ-মডেল এমন একটি মডেল যা দর্শন সত্তাকে প্রতিনিধিত্ব করে, আপনার মডেলটি ব্যবসায়িক সত্তাকে উপস্থাপন করে।

আপনি যদি পরে জুজু খেলা তৈরি করতে চান? ইউআই এর বেশিরভাগ অংশ পুনরায় ব্যবহারযোগ্য হওয়া উচিত। যদি আপনার গেম যুক্তি আপনার ভিউ-মডেলটিতে আবদ্ধ থাকে তবে ভিউ-মডেলটি পুনরায় প্রোগ্রাম না করে those উপাদানগুলিকে পুনরায় ব্যবহার করা খুব কঠিন be আপনি যদি আপনার ব্যবহারকারী ইন্টারফেস পরিবর্তন করতে চান? যদি আপনার গেম যুক্তি আপনার ভিউ-মডেল যুক্তির সাথে মিলিত হয় তবে আপনার গেমটি এখনও কাজ করে তা আপনাকে আবার পরীক্ষা করা দরকার। আপনি যদি একটি ডেস্কটপ এবং একটি ওয়েব অ্যাপ্লিকেশন তৈরি করতে চান? যদি আপনার ভিউ-মডেলটিতে গেম যুক্তি থাকে, তবে এই দুটি অ্যাপ্লিকেশন পাশাপাশি পাশাপাশি রাখার চেষ্টা করা জটিল হয়ে উঠবে কারণ অ্যাপ্লিকেশন যুক্তিটি অবশ্যম্ভাবীভাবে ভিউ-মডেলের ব্যবসায়িক যুক্তির সাথে আবদ্ধ হয়ে যায়।

ডেটা পরিবর্তন বিজ্ঞপ্তি এবং ডেটা বৈধকরণ প্রতিটি স্তরে ঘটে (ভিউ, ভিউ-মডেল এবং মডেল)।

মডেলটিতে আপনার ডেটা উপস্থাপনা (সত্তা) এবং সেই সত্তাগুলির সাথে সম্পর্কিত ব্যবসায়িক যুক্তি রয়েছে। কার্ডগুলির একটি ডেক হ'ল সহজাত বৈশিষ্ট্যযুক্ত একটি যৌক্তিক 'জিনিস'। একটি ভাল ডেকের মধ্যে সদৃশ কার্ডগুলি রাখা যায় না। এটি শীর্ষ কার্ড (গুলি) পাওয়ার জন্য একটি উপায় প্রকাশ করতে হবে। এটি ছেড়ে যাওয়ার চেয়ে বেশি কার্ড দিতে হবে না তা জানতে হবে। এই জাতীয় ডেক আচরণগুলি মডেলের অংশ, কারণ তারা কার্ডের ডেকের সহজাত nt এছাড়াও ডিলার মডেল, প্লেয়ার মডেল, হ্যান্ড মডেল ইত্যাদি থাকবে These এই মডেলগুলি ইন্টারেক্ট করতে পারে এবং করবে।

ভিউ-মডেলটিতে উপস্থাপনা এবং অ্যাপ্লিকেশন যুক্তি থাকবে। গেমটি প্রদর্শনের সাথে সম্পর্কিত সমস্ত কাজ গেমটির যুক্তি থেকে পৃথক। এর মধ্যে ইমেজ হিসাবে হাত প্রদর্শন, ডিলার মডেলকে কার্ডের জন্য অনুরোধ, ব্যবহারকারী প্রদর্শনের সেটিংস ইত্যাদি অন্তর্ভুক্ত থাকতে পারে

নিবন্ধটির সাহস:

মূলত, আমি যেভাবে এটি ব্যাখ্যা করতে চাই তা হ'ল আপনার ব্যবসায়িক যুক্তি এবং সত্তাগুলি মডেলকে অন্তর্ভুক্ত করে। আপনার নির্দিষ্ট অ্যাপ্লিকেশনটি এটি ব্যবহার করছে তবে এটি অনেকগুলি অ্যাপ্লিকেশন জুড়ে ভাগ করা যেতে পারে।

দৃশ্যটি হ'ল উপস্থাপনা স্তর - ব্যবহারকারীর সাথে সরাসরি ইন্টারফেসিং সম্পর্কিত যে কোনও কিছু।

ভিউমোডেলটি মূলত "আঠালো" যা আপনার অ্যাপ্লিকেশনের সাথে সুনির্দিষ্ট যা দুটিকে একসাথে যুক্ত করে।

আমার এখানে একটি চমৎকার চিত্র রয়েছে যা দেখায় যে তারা কীভাবে ইন্টারফেস করে:

http://reedcopsey.com/2010/01/06/better-user-and-developer-experiences-from-windows-forms-to-wpf-with-mvvm-part-7-mvvm/

আপনার ক্ষেত্রে - আসুন কয়েকটি সুনির্দিষ্ট সমাধান করতে ...

বৈধতা: এটি সাধারণত 2 ফর্ম আসে। ব্যবহারকারীর ইনপুট সম্পর্কিত বৈধতা ভিউমোডেলে (প্রাথমিকভাবে) এবং ভিউতে ঘটে (যেমন: "সংখ্যাযুক্ত" টেক্সটবক্স পাঠ্য প্রবেশ করানো থেকে রোধ করে আপনার জন্য ভিউ, ইত্যাদি পরিচালনা করা হয়)। এই হিসাবে, ব্যবহারকারী থেকে ইনপুটটির বৈধতা সাধারণত একটি ভিএম উদ্বেগ। বলা হচ্ছে, প্রায়শই বৈধতার দ্বিতীয় "স্তর" থাকে - এটি বৈধতা যা ব্যবহার করা হচ্ছে তা ব্যবসায়ের নিয়মের সাথে মেলে। এটি প্রায়শই নিজেরাই মডেলের অংশ is যখন আপনি আপনার মডেলটিতে ডেটা চাপান, এটি বৈধতা ত্রুটির কারণ হতে পারে। এরপরে ভিএমকে এই তথ্যটি ভিউতে পুনরায় তৈরি করতে হবে।

অপারেশনগুলি "কোনও দর্শন ছাড়াই পর্দার আড়ালে, যেমন ডিবিতে লেখা, ইমেল প্রেরণ করা ইত্যাদি": এটি সত্যই আমার চিত্রের "ডোমেন স্পেসিফিক অপারেশনস" এর একটি অংশ এবং সত্যিই নিখুঁতভাবে মডেলের অংশ। আপনি এটি অ্যাপ্লিকেশনটির মাধ্যমে প্রকাশ করার চেষ্টা করছেন। ভিউমোডেল এই তথ্যটি প্রকাশের জন্য সেতু হিসাবে কাজ করে, তবে অপারেশনগুলি খাঁটি-মডেল।

ভিউমোডেলের জন্য অপারেশনস: ভিউমোডেলকে কেবল আইএনপিসির চেয়েও বেশি প্রয়োজন - এটির জন্য আপনার অ্যাপ্লিকেশনের সাথে সুনির্দিষ্ট কোনও অপারেশন (আপনার ব্যবসার যুক্তি নয়) যেমন সংরক্ষণের পছন্দ এবং ব্যবহারকারীর অবস্থা ইত্যাদির প্রয়োজন এটি অ্যাপটি পরিবর্তিত করতে চলেছে। অ্যাপ দ্বারা।, একই "মডেল" ইন্টারফেস করার সময়ও।

এটি সম্পর্কে ভাবার একটি ভাল উপায় - বলুন আপনি নিজের অর্ডারিং সিস্টেমের 2 সংস্করণ তৈরি করতে চান। প্রথমটি ডব্লিউপিএফ এবং দ্বিতীয়টি একটি ওয়েব ইন্টারফেস।

অর্ডারগুলি নিজেরাই (ইমেল প্রেরণ, ডিবিতে প্রবেশ করা ইত্যাদি) সম্পর্কিত ভাগ করা যুক্তি হ'ল মডেল। আপনার অ্যাপ্লিকেশনটি এই ক্রিয়াকলাপগুলি এবং ডেটা ব্যবহারকারীর কাছে প্রকাশ করছে তবে এটি 2 উপায়ে করছে।

ডাব্লুপিএফ অ্যাপ্লিকেশনটিতে, ইউজার ইন্টারফেস (দর্শকের সাথে কীসের সাথে যোগাযোগ করে) হ'ল "ভিউ" - ওয়েব অ্যাপ্লিকেশনটিতে এটি মূলত কোড যা (অন্তত অবশেষে) ক্লায়েন্টের জাভাস্ক্রিপ্ট + এইচটিএমএল + সিএসএসে রূপান্তরিত হয়।

আপনি যে নির্দিষ্ট ভিউ প্রযুক্তি / স্তরটি ব্যবহার করছেন তা এটিকে কার্যকর করার জন্য ভিউমোডেলটি বাকি "আঠালো" যা আপনার মডেলটিকে (ক্রম সম্পর্কিত এই ক্রিয়াকলাপগুলি) মানিয়ে নিতে প্রয়োজন।


সম্ভবত একটি সাধারণ উদাহরণ একটি সঙ্গীত প্লেয়ার। আপনার মডেলগুলিতে গ্রন্থাগারগুলি এবং সক্রিয় শব্দ ফাইল এবং কোডেক এবং প্লেয়ার যুক্তি এবং ডিজিটাল সিগন্যাল প্রসেসিং কোড থাকবে। ভিউ-মডেলগুলিতে আপনার নিয়ন্ত্রণ এবং ভিজ্যুয়ালাইজেশন এবং গ্রন্থাগার ব্রাউজার থাকবে। সেই সমস্ত তথ্য প্রদর্শনের জন্য প্রচুর ইউআই যুক্তি প্রয়োজন এবং অন্য কোনও প্রোগ্রামারকে ইউআই স্বজ্ঞাত এবং মজাদার করার দিকে মনোনিবেশ করার সুযোগ দেওয়ার সময় কোনও প্রোগ্রামারকে সঙ্গীত খেলতে ফোকাস দেওয়ার অনুমতি দেওয়া ভাল লাগে। ভিউ-মডেল এবং মডেলটিকে সেই দুটি প্রোগ্রামারকে ইন্টারফেসের সেটগুলিতে একমত হতে এবং আলাদাভাবে কাজ করার অনুমতি দেওয়া উচিত।
ভোটকফি 20'14

আর একটি ভাল উদাহরণ একটি ওয়েব পৃষ্ঠা। সার্ভার-সাইড লজিক সাধারণত একটি মডেলের সমতুল্য। ক্লায়েন্ট-সাইড লজিক সাধারণত একটি ভিউ-মডেলের সমতুল্য। আমি সহজেই কল্পনা করব গেমের যুক্তিটি সার্ভারের সাথে সম্পর্কিত এবং ক্লায়েন্টের হাতে দেওয়া হবে না।
ভোটকফি

2

INotifyPropertyChanged এবং INotify Col લેક્ Changed উপর ভিত্তি করে বিজ্ঞপ্তি হ'ল আপনার যা প্রয়োজন। সম্পত্তির পরিবর্তনের সাবস্ক্রিপশন, সম্পত্তির নামের সংকলন-কালীন বৈধতা, মেমরি ফাঁস এড়ানো থেকে আপনার জীবনকে সহজ করার জন্য, আমি আপনাকে জোশ স্মিথের এমভিভিএম ফাউন্ডেশন থেকে প্রপার্টিঅবার্সার ব্যবহার করার পরামর্শ দিচ্ছি । এই প্রকল্পটি ওপেন সোর্স হিসাবে, আপনি উত্স থেকে আপনার প্রকল্পে কেবলমাত্র শ্রেণিটি যুক্ত করতে পারেন।

সম্পত্তি নিখরচারী কীভাবে ব্যবহার করবেন তা বোঝার জন্য এই নিবন্ধটি পড়ুন

এছাড়াও, রিঅ্যাকটিভ এক্সটেনশনগুলি (আরএক্স) আরও গভীরভাবে দেখুন । আপনি প্রকাশ করতে পারেন আপনার মডেল থেকে IObserver <T> করতে পারেন এবং ভিউ মডেলটিতে এটিতে সদস্যতা নিতে পারেন।


জোশ স্মিথস দুর্দান্ত নিবন্ধটি উল্লেখ করার জন্য এবং দুর্বল ইভেন্টগুলি কাভার করার জন্য আপনাকে অনেক ধন্যবাদ!
জেজেএস

1

ছেলেরা এর উত্তর দেওয়ার জন্য একটি আশ্চর্যজনক কাজ করেছে তবে এইরকম পরিস্থিতিতে আমি সত্যিই অনুভব করি যে এমভিভিএম প্যাটার্নটি একটি ব্যথা তাই আমি গিয়ে সুপারভাইজিং কন্ট্রোলার বা একটি প্যাসিভ ভিউ পদ্ধতির ব্যবহার করতে পারি এবং কমপক্ষে মডেল অবজেক্টগুলির জন্য বাইন্ডিং সিস্টেমটি যেতে পারি that তাদের নিজস্ব পরিবর্তন আনতে হয়।


1

আমি দিকনির্দেশক মডেলটির পক্ষে পরামর্শ দিচ্ছি -> মডেল দেখুন -> দীর্ঘকাল ধরে পরিবর্তনগুলির প্রবাহ দেখুন, আপনি ২০০৮ সাল থেকে আমার এমভিভিএম নিবন্ধের পরিবর্তন প্রবাহ বিভাগে দেখতে পাচ্ছেন । এটি বাস্তবায়ন প্রয়োজনINotifyPropertyChanged মডেলটিরআমি যতদূর বলতে পারি, এটি তখন থেকে সাধারণ অভ্যাস হয়ে ওঠে।

আপনি জোশ স্মিথকে উল্লেখ করেছেন বলে, তাঁর প্রপার্টি চেঞ্জ করা ক্লাসটি একবার দেখুন । এটি মডেলের সাবস্ক্রাইব করার জন্য একটি সহায়ক শ্রেণিINotifyPropertyChanged.PropertyChanged ইভেন্টটিতে ।

আপনি আমার প্রোপার্টিসআপডেটার ক্লাস তৈরি করে সাম্প্রতিককালে আসলেই আপনি এই পদ্ধতিকে আরও এগিয়ে নিতে পারেন । ভিউ-মডেলের বৈশিষ্ট্যগুলিকে জটিল এক্সপ্রেশন হিসাবে গণনা করা হয় যা মডেলটিতে এক বা একাধিক বৈশিষ্ট্য অন্তর্ভুক্ত করে।


1

INotifyPropertyChanged প্রয়োগ করার জন্য কোনও ভুল নেই অভ্যন্তরে এবং অভ্যন্তরে এটি শুনতে । বাস্তবে আপনি এমনকি এক্সএএমএল-তে মডেলের সম্পত্তিতে ডট করতে পারেন: {বাঁধাই মডেল od মডেলপ্রপার্টি}

নির্ভরযোগ্য / গণনাযোগ্য পঠনযোগ্য বৈশিষ্ট্যগুলির জন্য, এখন পর্যন্ত আমি এর চেয়ে ভাল এবং সহজ কিছুই দেখিনি: https://github.com/StephenCleary/CalculatedProperties । এটি অত্যন্ত সহজ তবে অবিশ্বাস্যভাবে কার্যকর, এটি সত্যই "এমভিভিএমের জন্য এক্সেল সূত্র" - এক্সেল আপনার পক্ষ থেকে অতিরিক্ত প্রচেষ্টা ছাড়াই সূত্রের কোষগুলিতে পরিবর্তনের প্রচারের মতোই কাজ করে।


0

আপনি মডেল থেকে ইভেন্টগুলি উত্থাপন করতে পারেন, যা ভিউমোডেলটির সাবস্ক্রাইব করতে হবে।

উদাহরণস্বরূপ, আমি সম্প্রতি একটি প্রকল্পে কাজ করেছি যার জন্য আমাকে ট্রিভিউ তৈরি করতে হয়েছিল (স্বাভাবিকভাবেই, মডেলটির এটির শ্রেণিবিন্যাসিক প্রকৃতি ছিল)। মডেলটিতে আমার একটি পর্যবেক্ষণযোগ্য কলকরণ বলা হয়েছিলChildElements

ভিউ মডেলটিতে, আমি মডেলটিতে অবজেক্টের একটি রেফারেন্স সঞ্চয় করে রেখেছিলাম এবং CollectionChangedপর্যবেক্ষণযোগ্য সংগ্রহের ইভেন্টটির সাবস্ক্রাইব করেছিলাম, ModelObject.ChildElements.CollectionChanged += new CollectionChangedEventHandler(insert function reference here)...

তারপরে আপনার ভিউ মডেলটি একবারে মডেলটিতে কোনও পরিবর্তন ঘটে automatically আপনি একই ধারণাটি ব্যবহার করে অনুসরণ করতে পারেন PropertyChangedতবে এটির জন্য আপনার মডেল থেকে সম্পত্তি পরিবর্তন ইভেন্টগুলি স্পষ্টভাবে বাড়াতে হবে।


তাহলে হায়ারারকিকাল ডাটা সঙ্গে যখন কারবারী, আপনি তাকান করতে চাইবেন ডেমো 2 এর আমার MVVM নিবন্ধ
শুভনোমাদ

0

এটি আমার কাছে সত্যিকারের গুরুত্বপূর্ণ প্রশ্নের মতো মনে হচ্ছে - এমনকি যখন এটি করার কোনও চাপ নেই। আমি একটি পরীক্ষা প্রকল্পে কাজ করছি, যার মধ্যে একটি ট্রিউউউ জড়িত। মেনু আইটেম এবং যেমন কমান্ড ম্যাপ করা হয় যেমন, মুছে ফেলুন। বর্তমানে, আমি ভিউ মডেলের মধ্যে থেকে মডেল এবং ভিউ মডেল উভয়কেই আপডেট করছি।

উদাহরণ স্বরূপ,

public void DeleteItemExecute ()
{
    DesignObjectViewModel node = this.SelectedNode;    // Action is on selected item
    DocStructureManagement.DeleteNode(node.DesignObject); // Remove from application
    node.Remove();                                // Remove from view model
    Controller.UpdateDocument();                  // Signal document has changed
}

এটি সহজ, তবে এটির খুব প্রাথমিক ত্রুটি রয়েছে বলে মনে হয়। একটি সাধারণ ইউনিট পরীক্ষা আদেশটি কার্যকর করে, তারপরে ভিউ মডেলটিতে ফলাফলটি পরীক্ষা করে। তবে এটি পরীক্ষা করে না যে মডেল আপডেটটি সঠিক ছিল, যেহেতু দু'জন একই সাথে আপডেট হয়েছে।

সুতরাং সম্ভবত মডেল আপডেটটিকে একটি ভিউ মডেল আপডেট ট্রিগার করতে প্রপার্টিবাজারের মতো কৌশল ব্যবহার করা ভাল। উভয় ক্রিয়া সফল হলে একই ইউনিট পরীক্ষা এখন কেবলমাত্র কাজ করবে।

এটি কোনও সম্ভাব্য উত্তর নয়, আমি বুঝতে পারি, তবে এটি সেখানে রাখার মতো মনে হয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.