2015-12-01 6 views
5

अगर मैं एक डेटा टेम्पलेट में {x:Bind {RelativeSource Self}} उपयोग करते हैं, मैं थोड़ी देर के संकलन निम्न त्रुटि मिलती है:मैं डेटा टेम्पलेट में {x: Bind {RelativeSource Self}} का उपयोग क्यों नहीं कर सकता?

वस्तु संदर्भ एक वस्तु का एक उदाहरण के लिए सेट नहीं।

विचार टेम्पलेट ऑब्जेक्ट को कमांड पैरामीटर जैसी संपत्ति पर पास करना है। यहाँ एक उदाहरण MainPage.xaml है:

<Page 
    x:Class="XBindTest5.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:XBindTest5" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d"> 

    <Page.Resources> 
     <ResourceDictionary> 
      <local:OpenItemCommand x:Key="OpenCommand"/> 
     </ResourceDictionary> 
    </Page.Resources> 

    <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
     <ItemsControl ItemsSource="{x:Bind NewsItems, Mode=OneWay}"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate x:DataType="local:NewsItem"> 
        <StackPanel> 
         <Button Command="{x:Bind {StaticResource OpenCommand}}" CommandParameter="{x:Bind {RelativeSource Self}}"> 
          <TextBlock Text="{x:Bind Title}"/> 
         </Button> 
        </StackPanel> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
    </StackPanel> 
</Page> 

एक साधारण मॉडल कोड-behinde फ़ाइल में MainPage.xaml.cs परिभाषित किया गया है:

using System; 
using System.Collections.ObjectModel; 
using System.Windows.Input; 
using Windows.UI.Xaml.Controls; 


namespace XBindTest5 { 

    public class NewsItem { 
     public string Title { get; set; } 
    } 

    /// <summary> 
    ///  command to open the item 
    /// </summary> 
    public class OpenItemCommand : ICommand { 

     public event EventHandler CanExecuteChanged; 

     public bool CanExecute(object parameter) { 
      return true; 
     } 

     public void Execute(object parameter) { 
      // ... example ... 
     } 
    } 

    public sealed partial class MainPage : Page { 

     public ObservableCollection<NewsItem> NewsItems { get; set; } 
      = new ObservableCollection<NewsItem>(new[] { 
       new NewsItem() { Title = "Item 1" }, 
       new NewsItem() { Title = "Item 2" } }); 

     public MainPage() { 
      this.InitializeComponent(); 
     } 
    } 
} 
+0

यदि आपको आश्चर्य है कि मैंने 'कमांड' को 'स्टेटिक रिसोर्स' के रूप में क्यों पारित किया है: मुझे डेटा एक्स टेम्पलेट में 'एक्स: बाइंड' के माध्यम से _outer_ गुणों का संदर्भ देने का कोई तरीका नहीं मिला। एक स्थिर संसाधन का उपयोग करना या तो काम नहीं करता है (एक और NullReferenceException बनाता है)। – ventiseis

+0

क्षमा करें, आप सही हैं। इसके बजाय इसे देखें: http://stackoverflow.com/questions/32372073/is-it-possible-to-use-compiled-binding-xbind-with-reletive-source-templated –

+0

ओह, आप सही हैं। उत्तर कहता है: _RelativeSource (एक्स: बाइंड के साथ) समर्थित नहीं है _। तो मुझे अपना मॉडल बदलना होगा .. मैंने केवल 'डेटामैप्लेट' के लिए खोज की है इसलिए मुझे यह जवाब याद आया। – ventiseis

उत्तर

9

हालांकि ऐसा लगता है आप समाधान कर लिया है अपने समस्या, मैं अभी भी भ्रम से बचने के लिए कुछ स्पष्टीकरण देना चाहता हूं और इसे भविष्य के पाठकों के लिए स्पष्ट रूप से बनाना चाहता हूं।

रूप @Peter Duniho उल्लेख किया है, {x:Bind}DataContext संपत्ति और {x:Bind} के साथ काम नहीं कर सकते हैं एक Source संपत्ति नहीं है, तो आप {x:Bind} में डेटा संदर्भ के रूप में StaticResource उपयोग नहीं कर सकते, लेकिन आप एक संपत्ति या एक का उपयोग कर सकते इसके बजाय स्थिर पथ। {x:Bind} का उपयोग करते समय, यह पृष्ठभूमि वर्ग का डेटा संदर्भ के रूप में उपयोग करता है। उदाहरण के लिए, जब आप ItemsSource="{x:Bind NewsItems, Mode=OneWay}" सेट करते हैं, तो यह XBindTest5.MainPage क्लास का डेटा संदर्भ के रूप में उपयोग करता है और इस श्रेणी की NewsItems संपत्ति ItemsSource पर बांधता है। और डेटा टेम्पलेट के अंदर, {x:Bind} अपने डेटा संदर्भ के रूप में x:DataType में घोषित कक्षा का उपयोग करता है। कृपया DataTemplate and x:DataType में स्पष्टीकरण निम्न पर ध्यान दें:

अंदर एक DataTemplate (चाहे एक आइटम टेम्पलेट, एक सामग्री टेम्पलेट, या एक शीर्ष लेख टेम्पलेट के रूप में प्रयोग किया जाता), पथ के मूल्य के संदर्भ में व्याख्या नहीं की है

पृष्ठ, लेकिन डेटा ऑब्जेक्ट के संदर्भ में टेम्पलेट किया जा रहा है। ताकि संकलन-समय पर इसकी बाइंडिंग को सत्यापित किया जा सके (और उनके लिए उत्पन्न कुशल कोड) डेटा टेम्पलेट को x का उपयोग करके अपने डेटा ऑब्जेक्ट के प्रकार की घोषणा करने की आवश्यकता है: डेटाटाइप

आपके मामले में, आप DataTemplate में Command उपयोग करते हैं, तो आप Command को यह संपत्ति NewsItem में एक OpenCommand संपत्ति जोड़ सकते हैं और बाध्य कर सकते हैं इसका इस्तेमाल करने की।

में अपने कोड-पीछे:

public class NewsItem 
{ 
    public string Title { get; set; } 
    public OpenItemCommand OpenCommand { get; set; } 
} 

XAML में:

<DataTemplate x:DataType="local:NewsItem"> 
    <StackPanel> 
     <Button Command="{x:Bind OpenCommand}" CommandParameter="{x:Bind}"> 
      <TextBlock Text="{x:Bind Title}" /> 
     </Button> 
    </StackPanel> 
</DataTemplate> 

इसके अलावा {x:Bind}{RelativeSource} का समर्थन नहीं करता है, आमतौर पर आप तत्व का नाम है और एक के रूप में Path में इसका नाम का उपयोग कर सकते वैकल्पिक। अधिक जानकारी के लिए {x:Bind} and {Binding} feature comparison देखें।

लेकिन इसका उपयोग DataTemplate में नहीं किया जा सकता है क्योंकि सभी PathNewsItem की संपत्ति माना जाता है।और आपके मामले में, मुझे लगता है कि आप NewsItemButton नहीं हैं, इसलिए NewsItem को CommandParameter के रूप में पास करने के लिए आप CommandParameter="{x:Bind}" का उपयोग कर सकते हैं।

पीएस: एक्सएएमएल डिजाइनर में एक छोटी सी बग है, आपको अभी भी Object reference not set to an instance of an object. त्रुटि मिल सकती है। आप वर्कअराउंड के रूप में {x:Bind } जैसे बाइंड के बाद एक स्पेस जोड़ सकते हैं।

+0

आपके बहुत ही कमजोर स्पष्टीकरण के लिए धन्यवाद। लेकिन एक छोटी टिप्पणी: 'सापेक्ष स्रोत का उपयोग करके ...'कमांड पैरामीटर के लिए मैंने वर्तमान' न्यूज़इटम 'को संदर्भित करने का प्रयास किया, बटन नहीं। इसलिए मैंने मार्कअप एक्सटेंशन को भी गलत समझा। – ventiseis

3

मुझे और अधिक विशेष रूप से इसका उत्तर दें। एक्स के लिए केवल एक संभावित डेटा संदर्भ है: बांधें और वह अंतर्निहित वर्ग है। एक पृष्ठ पर, यह पृष्ठ (या कोड-पीछे) है। डेटा टेम्पलेट में, यह डेटा टेम्पलेट की लक्ष्य प्रकार की संपत्ति में निर्दिष्ट बैकिंग क्लास है। एक तरफ, एक नियंत्रण टेम्पलेट में, एक्स: बाइंड बिल्कुल समर्थित नहीं है - हालांकि यह केवल समय की बात है।

यह सब कहना है कि x: डेटा का डेटा संदर्भ तय किया गया है, और यह कहां उपयोग किया जा रहा है, इस पर निर्भर करता है, मैं आपके XAML को देखे बिना डेटा संदर्भ बता सकता हूं। इतना कठोर क्यों? इसके आसपास कोड पीढ़ी को सरल बनाने के लिए। इसके अलावा, कार्यान्वयन को सरल बनाने के लिए भी। किसी भी मामले में, यह एक निश्चित नियम है, और सापेक्ष स्रोत, ElementName, और स्रोत और x: bind में समर्थित नहीं है।

इसका मतलब यह नहीं है कि आप रिश्तेदार संसाधन स्वयं का संदर्भ नहीं दे सकते हैं, आपको बस इसे निर्दिष्ट x: name के साथ करना है। आप इस <Tag x:Name="Jerry" Tag="Nixon" Text="{x:Bind Jerry.Tag}" /> की तरह कुछ करेंगे।

वह विशेष नमूना क्यों विफल रहता है? {binding} के विपरीत, {x:bind} मिलान प्रकारों की आवश्यकता है, जिसका अर्थ है कि पाठ की स्ट्रिंग को डाउन-कास्ट सेट किया जा सकता है और टैग की ऑब्जेक्ट पर सेट किया जा सकता है, लेकिन टैग की ऑब्जेक्ट को अप-कास्ट नहीं किया जा सकता है और टेक्स्ट के स्ट्रिंग मान पर सेट नहीं किया जा सकता है। आपके लिए दूर ले जाकर एक्स का उपयोग कर रहा है: बाइंड का मतलब है कि आपके प्रकार का मिलान होना चाहिए।

मुझे आशा है कि यह आपको आगे बढ़ने में मदद करेगा।

शुभकामनाएं।

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