2009-04-08 19 views
17

मैं सिल्वरलाइट 2.0 में एक सरल पहेली पहेली गेम बनाने की कोशिश कर रहा हूं। मैं UserControl-ish घटक पर काम कर रहा हूं जो पहेली में एक वर्ग का प्रतिनिधित्व करता है। मुझे अपने UserControl के गुणों को अपने 'तत्वों के साथ बाध्य करने में परेशानी हो रही है। आखिरकार मैंने (काम किया) इसे काम कर लिया है (कुछ के लिए सहायक हो सकता है - मुझे कुछ घंटे लग गए), लेकिन इसे और अधिक 'सुरुचिपूर्ण' बनाना चाहता था।बाध्यकारी सिल्वरलाइट UserControl अपने गुणों के लिए कस्टम गुण

मैंने कल्पना की है कि इसमें सामग्री और एक लेबल (ऊपरी दाएं कोने में) के लिए एक डिब्बे होना चाहिए जिसमें वैकल्पिक रूप से इसकी संख्या शामिल है। सामग्री नियंत्रण शायद टेक्स्टबॉक्स हो, जबकि लेबल नियंत्रण टेक्स्टब्लॉक हो सकता है।

<UserControl x:Class="XWord.Square" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    FontSize="30" 
    Width="100" Height="100"> 
     <Grid x:Name="LayoutRoot" Background="White"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*"/> 
       <ColumnDefinition Width="Auto"/> 
      </Grid.ColumnDefinitions> 

      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="*"/> 
      </Grid.RowDefinitions> 

      <TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1" 
       Text="7"/> 
      <TextBox x:Name="Content" Grid.Row="1" Grid.Column="0" 
       Text="A" 
       BorderThickness="0" /> 

     </Grid> 
    </UserControl> 

मैं भी इस तरह स्क्वायर वर्ग में DependencyProperties बना लिया है:: तो मैं इस बुनियादी संरचना के साथ एक UserControl (मानों इस स्तर पर hardcoded कर रहे हैं) बनाया अब

 public static readonly DependencyProperty LabelTextProperty; 
    public static readonly DependencyProperty ContentCharacterProperty; 

    // ...(static constructor with property registration, .NET properties 
    // omitted for brevity)... 

मैं था लेबल और सामग्री तत्व को दो गुणों में कैसे बांधना है, यह समझना पसंद है। मैं इसे इस तरह करता हूं (कोड-बैक फ़ाइल में):

 Label.SetBinding(TextBlock.TextProperty, new Binding { Source = this, Path = new PropertyPath("LabelText"), Mode = BindingMode.OneWay }); 
    Content.SetBinding(TextBox.TextProperty, new Binding { Source = this, Path = new PropertyPath("ContentCharacter"), Mode = BindingMode.TwoWay }); 

यह एक्सएएमएल में अधिक सुरुचिपूर्ण होगा। क्या किसी को पता है कि यह कैसे किया जाता है?

+3

इस तरह के एक महत्वपूर्ण सवाल अभी तक एक भ्रामक जवाब है। –

उत्तर

1

मैं आपकी समस्या को बिल्कुल समझ नहीं सकता। सिल्वरलाइट में, आप लगभग किसी भी डेटा ऑब्जेक्ट से जुड़ने में सक्षम हैं। इसलिए, यदि आपके पास एक पहेली स्क्वायर क्लास है जिसमें गुण सामग्री और लेबल शामिल हैं, तो आप ऑब्जेक्ट से सीधे इन गुणों से जुड़ सकते हैं।

मान लीजिए कि आप एक साधारण वस्तु PuzzleSquare बनाया करते हैं:

public class PuzzleSquare 
    { 
     public string Content{ get; set; } 
     public string Label{ get; set; } 

     public void PuzzleSquare(){}; 
     public void PuzzleSquare(string label, string content):this() 
     { 
     Content = content; 
     Label = label; 
     }  
    } 

तो, आप मॉडल के पीछे क्लासिक दृश्य/कोड के साथ अनुप्रयोग का निर्माण कर रहे हैं, तो आपके कोड के पीछे की DataContext संपत्ति को यह वस्तु जोड़ना होगा पृष्ठ लोड पर ग्रिड:

LayoutRoot.DataContext = new PuzzleSquare("1", "A"); 

आपका Xaml स्क्वायर संपत्ति के लिए बाध्य होगा:

<TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1" 
Text="{Binding Label}"/>    
    <TextBox x:Name="Content" Grid.Row="1" Grid.Column="0" 
Text="{Binding Content}" BorderThickness="0" /> 

क्या यह समझ में आता है?

ib।

+1

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

+0

वहां वर्णों से बाहर निकलें .. तो मेरे डिजाइन में, मैं अपनी कक्षा का उपयोग .. हालांकि, मुझे सामग्री संपत्ति को स्क्वायर के उप-समूह में तार करने की आवश्यकता है। क्या इसका कोई मतलब है? –

2

मुझे लगता है कि आप UI Element to Element Binding लिए देख रहे हैं जो सिल्वरलाइट की एक विशेषता है 3.

+0

जेम्स कैड ने कहा: यदि आप एप्लिकेशन में UserControl का उपभोग करते हैं और इसे एक नाम देते हैं तो यह तोड़ता है। –

19

पहले, UserControl का उपयोग करना {RelativeSource स्व} को DataContext सेट:

<UserControl x:Class="XWord.Square" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
FontSize="30" 
Width="100" Height="100" 
DataContext="{Binding RelativeSource={RelativeSource Self}}"> 

अब आप व्यक्तिगत बाध्य कर सकते हैं usercontrol के गुणों के तत्वों:

<TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1" 
Text="{Binding LabelText}"/> 
<TextBox x:Name="Content" Grid.Row="1" Grid.Column="0" 
Text="{Binding ContentCharacter}" BorderThickness="0" /> 

SL 2.0 के लिए, आप UserControl की लोडेड ईवेंट हैंडलर पर DataContext सेट करना होगा ।

private void UserControl_Loaded(object sender, RoutedEventArgs e) { 
    LayoutRoot.DataContext = this; 
} 
+0

क्या यह एमवीवीएम अच्छे प्रथाओं का बिल्कुल विपरीत तरीका नहीं है? एमवीवीएम दुनिया में, UserControl का DataContext को ViewModel पर सेट किया जाना चाहिए। क्या होगा यदि मैं ViewModel पर नियंत्रण बांधना चाहता हूं, और दूसरा मेरे UserControl की संपत्ति के लिए? – JYL

+0

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

0

यह सिल्वरलाइट 4 में काम करता है।0

UserControl पर कोई नाम दें, और

<UserControl x:Class="XWord.Square" 
    ...omitted for brevity ... 
    x:Name="Square"> 

     <TextBlock x:Name="Label" ... 
      Text="{Binding Path=LabelText,ElementName=Square}"/> 
+1

यदि आप एप्लिकेशन में UserControl का उपभोग करते हैं और इसे एक नाम देते हैं तो यह तोड़ता है। –

+0

लेकिन फिर भी समाधान का प्रकार – Evgeny

7

सिल्वरलाइट FindAncestor तकनीक का उपयोग नहीं कर सकते हैं के रूप में आप एक चाल है कि एक UserControl का नाम सेट के लिए इसी तरह उपयोग कर सकते हैं TextBlock में इसे करने के लिए तो उल्लेख है, लेकिन बिना LayoutRoot के नाम का उपयोग करके अपनी कार्यक्षमता को तोड़ने के ...

<UserControl x:Class="XWord.Square" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
FontSize="30" 
Width="100" Height="100"> 
    <Grid x:Name="LayoutRoot" Background="White"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="Auto"/> 
     </Grid.ColumnDefinitions> 

     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="*"/> 
     </Grid.RowDefinitions> 

     <TextBlock x:Name="{Binding Path=Parent.LabelText, ElementName=LayoutRoot}" Grid.Row="0" Grid.Column="1" 
      Text="7"/> 
     <TextBox x:Name="{Binding Path=Parent.ContentCharacter, ElementName=LayoutRoot}" Grid.Row="1" Grid.Column="0" 
      Text="A" 
      BorderThickness="0" /> 
    </Grid> 
</UserControl> 

यह किसी भी अतिरिक्त कोड (मैं एक WP7 के अनुप्रयोग में यह उपयोग कर रहा हूँ) जोड़े बिना SL3 में काम किया, लेकिन पता है अगर तुम नहीं करते एसएल 2 में इसका इस्तेमाल कर सकते हैं। खैर, मुझे एहसास हुआ कि यह सवाल पुराना है, उम्मीद है कि यह अभी भी सहायक है, मैं यहां पहुंचा हूं क्योंकि WP7 में एक ही समस्या के लिए मुझे जो जवाब मिले हैं, वह मुझे विश्वास नहीं दिलाता है।

+0

इस पृष्ठ के समाधानों में से यह एकमात्र मान्य जैसा लगता है, हालांकि यह काफी अजीब है कि मैं सिर्फ नाम से कोड में अपनी सामग्री शुरू करने जा रहा हूं। –

0

इस प्रयास करें:

Public ReadOnly TextProperty As DependencyProperty = DependencyProperty.Register("Text", GetType(String), GetType(ButtonEdit), New System.Windows.PropertyMetadata("", AddressOf TextPropertyChanged)) 
Public Property Text As String 
    Get 
     Return GetValue(TextProperty) 
    End Get 
    Set(ByVal value As String) 
     SetValue(TextProperty, value) 
    End Set 
End Property 
Private Sub TextPropertyChanged() 
    If String.IsNullOrEmpty(Text) Then 
     TextBox1.Text = "" 
    Else 
     TextBox1.Text = Text 
    End If 
End Sub 
Private Sub TextBox1_LostFocus(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles TextBox1.LostFocus 
    Text = TextBox1.Text 
End Sub 

मैं दोनों XAML और पीछे कोड में बाध्य कर सकते हैं।