2015-09-05 9 views
7

में एकाधिक आइटम प्रकारों के लिए यूडब्ल्यूपी डेटा टेम्पलेट्स मैं इसे लागू करने के बारे में कैसे जाउंगा?सूची दृश्य

मान लें कि यह मेरा मॉडल है:

public interface IAnimal 
{ 
    string Name { get; } 
} 
public class Fish : IAnimal 
{ 
    public string Name { get; set; } 
    public int ScalesCount { get; set; } 
} 
public class Dog : IAnimal 
{ 
    public string Name { get; set; } 
    public string CollarManufacturerName { get; set; } 
} 

public class ViewModel 
{ 
    public ObservableCollection<IAnimal> Animals { get; set; } 

    public ViewModel() 
    { 
     this.Animals = new ObservableCollection<IAnimal>(); 
     this.Animals.Add(new Fish { Name = "Carl", ScalesCount = 9000 }); 
     this.Animals.Add(new Dog { Name = "Fifi", CollarManufacturerName = "Macrosoft" }); 
    } 
} 

इस सवाल में कोड की राशि की खातिर के लिए कृपया मान लेते हैं कि INotifyPropertyChanged कार्यान्वित किया जाता है जहां आवश्यक हो, और कहा कि ViewModel सही ढंग से पेज में आरंभ नहीं हो जाता।

मैं अपने संबंधित डेटा टेम्पलेट्स का उपयोग कैसे कर सकता हूं? डब्ल्यूपीएफ में मैं x:Key के बिना कई डेटा टेम्पलेट्स को परिभाषित करता हूं लेकिन परिभाषित डेटाटाइप के साथ और सूची दृश्य को आइटम के प्रकार के आधार पर उपयोग करने के लिए चुना गया है। यूडब्ल्यूपी इसे पसंद नहीं करता है; कंपाइलर बस Dictionary Item "DataTemplate" must have a Key attribute बताता है। तो मैं अपना लक्ष्य कैसे पूरा करूं?

वर्तमान प्रयास

मेरे वर्तमान प्रयास एक कस्टम DataTemplateSelector, जो बल्कि सीधे आगे लगता है बनाने के लिए है।

public class MyDataTemplateSelector: Windows.UI.Xaml.Controls.DataTemplateSelector 
{ 
    public ObservableCollection<TemplateMatch> Matches { get; set; } 

    public DataTemplateSelector() 
    { 
     this.Matches = new ObservableCollection<TemplateMatch>(); 
    } 

    protected override DataTemplate SelectTemplateCore(object item) 
    { 
     return this.Matches.FirstOrDefault(m => m.TargetType.Equals(item))?.Template; 
    } 

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 
    { 
     return this.Matches.FirstOrDefault(m => m.TargetType.Equals(item))?.Template; 
    } 
} 

public class TemplateMatch 
{ 
    public Type TargetType { get; set; } 
    public DataTemplate Template { get; set; } 
} 

इस तरह XAML में यह निर्धारित करें:

<ListView ItemsSource="{x:Bind ViewModel.Animals}"> 
    <ListView.ItemTemplateSelector> 
     <cmp:MyDataTemplateSelector> 
      <cmp:MyDataTemplateSelector.Matches> 
       <cmp:TemplateMatch TargetType="model:Dog" Template="{StaticResource DogTemplate}"/> 
       <cmp:TemplateMatch TargetType="model:Fish" Template="{StaticResource FishTemplate}"/> 
      </cmp:MyDataTemplateSelector.Matches> 
     </cmp:MyDataTemplateSelector> 
    </ListView.ItemTemplateSelector> 
</ListView> 

दुर्भाग्य से जब मैं इस चलाने के लिए, एक अपवाद रनटाइम के दौरान, तब होता है Failed to create a 'Ui.Components.TemplateMatch' from the text 'model:Dog'. बताते हुए तो ऐसा लगता है एक Type संपत्ति के लिए बाध्य है कि आसान नहीं है।

किसी भी मदद की सराहना की जाती है!

कृपया ध्यान दें कि मैं, के रूप में string करने का विरोध किया, जहां मैं CLR प्रकार नाम से होकर गुजरेगा और प्रकार आह्वान करने के लिए प्रतिबिंब का उपयोग प्रकार Type की संपत्ति का उपयोग करना चाहते ज्यादातर क्योंकि मैं मिश्रित CLR और एक्सएमएल नहीं करना चाहते XAML में नामस्थान दिखाई देते हैं। यदि आप XML नामस्थान का उपयोग करके प्रकार का आह्वान करने का कोई तरीका ढूंढ सकते हैं, तो मैं खुशी से इसे उत्तर के रूप में ले जाऊंगा।

+0

क्या आपने TargetType = "{x: टाइप मॉडल: डॉग}" का प्रयास किया है क्योंकि संपत्ति प्रकार "प्रकार" और स्ट्रिंग नहीं है। –

+0

मैंने किया। यूडब्लूपी एक्स का समर्थन नहीं करता है: अब मार्कअप टाइप करें। यह डब्ल्यूपीएफ के लिए समाधान होगा। :) –

+0

टेम्पलेटमैच का उपयोग करने के बजाय चुनिंदा टेम्पलेट विधि के अंदर सशर्त कथन क्यों न बनाएं? – Lance

उत्तर

2

मुझे कामकाज मिला। आप इन प्रकार के उदाहरण बनाने में सक्षम है - आप का पता लगाने के प्रकार के लिए उपयोग कर सकते हैं:

[ContentProperty(Name = nameof(Matches))] 
public class TypeTemplateSelector : DataTemplateSelector 
{ 
    public ObservableCollection<TemplateMatch> Matches { get; set; } 
    public TypeTemplateSelector() 
    { 
     this.Matches = new ObservableCollection<TemplateMatch>(); 
    } 

    protected override DataTemplate SelectTemplateCore(object item) 
    { 
     return this.Matches.FirstOrDefault(m => m.ItemOfType.GetType().Equals(item.GetType()))?.TemplateContent; 
    } 

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 
    { 
     return this.Matches.FirstOrDefault(m => m.ItemOfType.GetType().Equals(item.GetType()))?.TemplateContent; 
    } 
} 

[ContentProperty(Name = nameof(ItemOfType))] 
public class TemplateMatch 
{ 
    public object ItemOfType { get; set; } 
    public DataTemplate TemplateContent { get; set; } 
} 

XAML:

<controls:TypeTemplateSelector> 
    <controls:TemplateMatch TemplateContent="{StaticResource FishTemplate}"> 
     <models:Fish/> 
    </controls:TemplateMatch> 
    <controls:TemplateMatch TemplateContent="{StaticResource DogTemplate}"> 
     <models:Dog/> 
    </controls:TemplateMatch> 
</controls:TypeTemplateSelector> 
+0

@ निक का उत्तर इस जैसा है (@ नेकिटोएसपी का जवाब)। लेकिन मुझे यह पसंद है कि यह पूर्ण नाम स्ट्रिंग की तुलना करने के बजाय प्रकारों की तुलना करता है। – terry

0

सुराग त्रुटि संदेश में है।

पाठ से एक 'Ui.Components.TemplateMatch' बनाने में विफल 'मॉडल: कुत्ता'

नोट 'मॉडल: कुत्ता' नहीं पाठ एक प्रकार के रूप में अपने चयनकर्ता लिए आ रहा है।

इस तरह लिखने के बजाय स्ट्रिंग के लिए अपनी TemplateMatch वर्ग TargetType संपत्ति बदलें: -

public class TemplateMatch 
{ 
    public string TargetType { get; set; } 
    public DataTemplate Template { get; set; } 
} 

फिर

public class MyDataTemplateSelector : DataTemplateSelector 
{ 
    public ObservableCollection<TemplateMatch> Matches { get; set; } 

    public MyDataTemplateSelector() 
    { 
     Matches = new ObservableCollection<TemplateMatch>(); 
    } 

    protected override DataTemplate SelectTemplateCore(object item) 
    { 
     return Matches.FirstOrDefault(m => m.TargetType.Equals(item.GetType().ToString()))?.Template; 
    } 

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 
    { 
     return Matches.FirstOrDefault(m => m.TargetType.Equals(item.GetType().ToString()))?.Template; 
    } 
} 

पढ़ने के लिए अपने टेम्पलेट चयनकर्ता वर्ग बदलने के अंत में अपने XAML बदलने को पढ़ने के लिए

<ListView ItemsSource="{x:Bind ViewModel.Animals}"> 
    <ListView.ItemTemplateSelector> 
     <cmp:MyDataTemplateSelector> 
      <cmp:MyDataTemplateSelector.Matches> 
       <cmp:TemplateMatch TargetType="YourFullNamespaceNotXamlNamespace.Dog" Template="{StaticResource DogTemplate}"/> 
       <cmp:TemplateMatch TargetType="YourFullNamespaceNotXamlNamespace.Fish" Template="{StaticResource FishTemplate}"/> 
      </cmp:MyDataTemplateSelector.Matches> 
     </cmp:MyDataTemplateSelector> 
    </ListView.ItemTemplateSelector> 
</ListView> 

बिंदु यह है कि इसे अपने चयनकर्ता को पास करने की कोशिश करना भूल जाए ype, और टाइपनाम को एक स्ट्रिंग के रूप में पास करें (पूर्ण नामस्थान Xaml नेमस्पेस नहीं है)।

+0

यह एक संभावित समाधान है, लेकिन मैं वास्तव में 'टाइप' प्रकार की संपत्ति से जुड़ना चाहता हूं। आप जानते हैं, सामान्य डेटा टेम्पलेट्स की तरह करते हैं। इसके अलावा, जब मैं एक्सएएमएल में हूं, तो सीएलआर नेमस्पेस का उपयोग एक ही स्थान पर और दूसरे में एक्सएमएल नेमस्पेस का उपयोग करना वास्तव में सीधे आगे नहीं है। मुझे पता है कि यह एक कामकाज पर नापसंद है, लेकिन मैं सही जवाब खोजना चाहता हूं। –

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