2012-04-13 5 views
7

मैं this article और अन्य संसाधनों का उपयोग करके धीरे-धीरे WPF सीख रहा हूं।WPF में ViewModels से गतिशील रूप से सरल दृश्य जेनरेट करें?

मैं एप्लिकेशन तर्क पर ध्यान केंद्रित कर रहा हूं - मॉडल + व्यू मॉडेल को परिभाषित करना, और इन पर काम करने वाले आदेश बनाना। मैंने अभी तक दृश्य और .xaml प्रारूप को नहीं देखा है।

जबकि मैं तर्क पर काम कर रहा हूं, मैं एक ऐसा दृश्य देखना चाहता हूं जो किसी भी दृश्य को प्रस्तुत कर सके। मॉडल मैं इसे बांधता हूं। दृश्य

  • पाठ बॉक्स के रूप में भी सार्वजनिक string गुण प्रदान करना चाहिए, और संपत्ति
  • पाठ बॉक्स बाँध एक लेबल के रूप गुण का नाम को प्रस्तुत करें।
  • भी सार्वजनिक 'कमांड' एक बटन के रूप संपत्ति प्रदान, और आदेश के लिए बटन बाँध (शायद ही अगर आदेश का कोई तर्क लेता है?)

संभव कुछ इस तरह है, जबकि MVVM डिजाइन पैटर्न maintaing है? यदि हां, तो मैं इसे कैसे प्राप्त करूं? साथ ही, लेख .xaml कोडबेंड का उपयोग करने से बचने का सुझाव देता है - क्या यह दृश्य शुद्ध xaml में लागू किया जा सकता है?

+0

मैं एक बहुत अच्छा विचार लगता है कि thats! आपके पास बिना किसी बुनियादी यूआई के कामकाजी आवेदन हो सकता है और डिजाइनर काम शुरू होने से पहले व्यूमोडेल/मॉडल का परीक्षण शुरू कर सकता है। =) – Jens

+0

आपको अपने व्यूमोडेल का परीक्षण करने के लिए दृश्य की आवश्यकता नहीं है। कि mvvm के लिए क्या;) – blindmeis

+0

आपको * यूनिट * को व्यूमोडेल का परीक्षण करने की आवश्यकता नहीं है, लेकिन मुझे लगता है कि एक मूल UI'd यह देखने में बहुत मददगार होगा कि सभी घटक ठीक से काम करते हैं या नहीं। – Jens

उत्तर

6

मुझे नहीं लगता कि यह केवल एक्सएएमएल में संभव है। यदि आप रनटाइम में अपने विचार जेनरेट करना चाहते हैं तो आपको अपने व्यू मॉडल्स पर प्रतिबिंब का उपयोग करना होगा और तदनुसार नियंत्रण उत्पन्न करना होगा। यदि आप संकलन समय पर विचार उत्पन्न करना चाहते हैं तो आप अपने टेम्पलेट इंजन (जैसे टी 4 या स्ट्रिंग टेम्पलेट) या कोडडॉम के साथ बिल्ड समय पर अपने व्यू मॉडल्स से एक्सएएमएल फाइलें जेनरेट कर सकते हैं। या आप आगे जा सकते हैं और कुछ मेटाडाटा प्रारूप (या यहां तक ​​कि डीएसएल) भी कर सकते हैं जिससे आप मॉडल और विचार दोनों उत्पन्न करेंगे। यह आपके ऐप की जरूरतों पर निर्भर है।

और एमवीवीएम कोड-बैक में भी दृश्य तर्क के लिए ठीक है और मॉडल/व्यूमोडेल के लिए बाध्यकारी है जो केवल एक्सएएमएल में नहीं किया जा सकता है।

3

मुझे यकीन नहीं है कि यह "शुद्ध एमवीवीएम" दृष्टिकोण के लिए उपयुक्त उपयोग है, निश्चित रूप से बाध्यकारी द्वारा सबकुछ हासिल नहीं किया जा रहा है। और मैं यहां आपके "दृश्य" के लिए कोड-बैक का उपयोग करने से बचने का विचार फेंक दूंगा, यह एक स्वाभाविक रूप से प्रोग्रामेटिक कार्य है। एक चीज जो आपको चिपकनी चाहिए वह व्यूमोडेल को दृश्य का कोई ज्ञान नहीं दे रहा है, ताकि जब आप इसे "वास्तविक चीज़" से बदल दें तो ऐसा करने के लिए कोई काम नहीं है।

लेकिन निश्चित रूप से उचित काम करना प्रतीत होता है; यह लगभग एक डिबगिंग विज़ुअलाइज़र की तरह लगता है - आप इसके लिए एक मौजूदा उपकरण का लाभ उठाने में सक्षम हो सकते हैं।

(यदि आप मानक ItemsControl एस और टेम्पलेट्स के साथ अधिकतर एक्सएएमएल में ऐसा करना चाहते हैं तो आप अपने व्यूमोडेल के गुणों को बेनकाब करने के लिए एक कनवर्टर लिख सकते हैं, जिसे आप बाध्य कर सकते हैं, आवरण के साथ रैपर ऑब्जेक्ट्स का संग्रह मेटाडाटा, लेकिन मुझे लगता है कि यह सुनिश्चित करने के लिए कि संपत्तियों का खुलासा किया गया है, ठीक से बाध्य करने योग्य है, इसके लायक से अधिक काम होगा)

1

सूचक: विशिष्ट वीएम (लक्ष्य) से जुड़ी एक स्ट्रिंग के रूप में एक गतिशील डेटा टेम्पलेट उत्पन्न करें। XamlReader के माध्यम से इसे पार्स करें। कोड में अपने ऐप संसाधनों में इसे प्लोन करें।

बस एक विचार .. इसके साथ चलें .. दृश्य या व्यूमोडेल के अलावा किसी अन्य प्रकार से किया जाना चाहिए।

3

मैं अब इसे लागू करने के माध्यम से आधे रास्ते में हूं, मुझे आशा है कि निम्न कोड किसी और को ऐसा करने की कोशिश करने में मदद करेगा। एक और मजबूत पुस्तकालय में बदलना मजेदार हो सकता है।

AbstractView.xaml:

<UserControl x:Class="MyApplication.View.AbstractView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <StackPanel Name="container"> 
    </StackPanel> 
</UserControl> 

AbstractView.xaml.cs:

public partial class AbstractView : UserControl 
{ 
    public AbstractView() 
    { 
     InitializeComponent(); 

     DataContextChanged += Changed; 
    } 

    void Changed(object sender, DependencyPropertyChangedEventArgs e) 
    { 
     object ob = e.NewValue; 
     var props = ob.GetType().GetProperties(); 

     List<UIElement> uies = new List<UIElement>(); 
     foreach (var prop in props) 
     { 
      if (prop.PropertyType == typeof(String)) 
       uies.Add(makeStringProperty(prop)); 
      else if (prop.PropertyType == typeof(int)) 
       uies.Add(makeIntProperty(prop)); 
      else if (prop.PropertyType == typeof(bool)) 
       uies.Add(makeBoolProperty(prop)); 
      else if (prop.PropertyType == typeof(ICommand)) 
       uies.Add(makeCommandProperty(prop)); 
      else 
      { 
      } 
     } 

     StackPanel st = new StackPanel(); 
     st.Orientation = Orientation.Horizontal; 
     st.HorizontalAlignment = HorizontalAlignment.Center; 
     st.Margin = new Thickness(0, 20, 0, 0); 
     foreach (var uie in uies) { 
      if (uie is Button) 
       st.Children.Add(uie); 
      else 
       container.Children.Add(uie); 
     } 
     if (st.Children.Count > 0) 
      container.Children.Add(st); 

    } 

    UIElement makeCommandProperty(PropertyInfo prop) 
    { 
     var btn = new Button(); 
     btn.Content = prop.Name; 

     var bn = new Binding(prop.Name); 
     btn.SetBinding(Button.CommandProperty, bn); 
     return btn; 
    } 

    UIElement makeBoolProperty(PropertyInfo prop) 
    { 
     CheckBox bx = new CheckBox(); 
     bx.SetBinding(CheckBox.IsCheckedProperty, getBinding(prop)); 
     if (!prop.CanWrite) 
      bx.IsEnabled = false; 
     return makeUniformGrid(bx, prop); 
    } 

    UIElement makeStringProperty(PropertyInfo prop) 
    { 
     TextBox bx = new TextBox(); 
     bx.SetBinding(TextBox.TextProperty, getBinding(prop)); 
     if (!prop.CanWrite) 
      bx.IsEnabled = false; 

     return makeUniformGrid(bx, prop); 
    } 

    UIElement makeIntProperty(PropertyInfo prop) 
    { 
     TextBlock bl = new TextBlock(); 
     bl.SetBinding(TextBlock.TextProperty, getBinding(prop)); 

     return makeUniformGrid(bl, prop); 
    } 

    UIElement makeUniformGrid(UIElement ctrl, PropertyInfo prop) 
    { 
     Label lb = new Label(); 
     lb.Content = prop.Name; 

     UniformGrid u = new UniformGrid(); 
     u.Rows = 1; 
     u.Columns = 2; 
     u.Children.Add(lb); 
     u.Children.Add(ctrl); 

     return u; 
    } 

    Binding getBinding(PropertyInfo prop) 
    { 
     var bn = new Binding(prop.Name); 
     if (prop.CanRead && prop.CanWrite) 
      bn.Mode = BindingMode.TwoWay; 
     else if (prop.CanRead) 
      bn.Mode = BindingMode.OneWay; 
     else if (prop.CanWrite) 
      bn.Mode = BindingMode.OneWayToSource; 
     return bn; 
    } 

} 
+0

क्या आप अंतिम परियोजना के लिए एक लिंक प्रदान कर सकते हैं (यदि यह खुला सोर्स किया गया था)? मुझे यह देखने में बहुत दिलचस्पी होगी कि यह कैसा दिखता है और आप क्या करने में कामयाब रहे। – bachr

संबंधित मुद्दे