2012-12-19 38 views
16

ठीक है, मुझे पता है। यह सचमुच दस लाख बार पूछा गया है, लेकिन मुझे अभी भी यह नहीं मिला है। उसके लिए खेद है।कस्टम निर्भरता संपत्ति के लिए बाध्यकारी - फिर

कार्य: सरल निर्भरता संपत्ति कभी लागू है, जो इस तरह XAML में इस्तेमाल किया जा सकता है:

<uc:MyUserControl1 MyTextProperty="{Binding Text}"/> 

मुझे लगता है कि this जवाब काफी करीब है। बेहतर पठनीयता के लिए मैं यहां अपना पूरा कोड कॉपी करता हूं (अधिकतर उस उत्तर से ऊपर)।

<UserControl x:Class="Test.UserControls.MyUserControl1" 
      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" 
      DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <Grid> 
     <!-- Text is being bound to outward representative property; 
      Note the DataContext of the UserControl --> 
     <TextBox Text="{Binding MyTextProperty}"/> 
    </Grid> 
</UserControl> 

और

public partial class MyUserControl1 : UserControl 
{ 
    // The dependency property which will be accessible on the UserControl 
    public static readonly DependencyProperty MyTextPropertyProperty = 
     DependencyProperty.Register("MyTextProperty", typeof(string), typeof(MyUserControl1), new UIPropertyMetadata(String.Empty)); 
    public string MyTextProperty 
    { 
     get { return (string)GetValue(MyTextPropertyProperty); } 
     set { SetValue(MyTextPropertyProperty, value); } 
    } 

    public MyUserControl1() 
    { 
     InitializeComponent(); 
    } 
} 

और ये मेरे MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:uc="clr-namespace:WpfApplication1" 
     Title="MainWindow" Height="350" Width="525"> 
    <StackPanel Orientation="Vertical"> 
     <uc:MyUserControl1 MyTextProperty="my text goes here"/> 
     <Button Click="ButtonBase_OnClick" Content="click"/> 
    </StackPanel> 
</Window> 

अब तक है, सब कुछ काम करता है। हालांकि, मुझे यह काफी उपयोगी नहीं लगता है। क्या मैं आवश्यकता होगी

<uc:MyUserControl1 MyTextProperty="{Binding Text}"/> 

और एक DataContext सेट करके ऐसा बदलने के लिए सक्षम किया जा रहा है (जैसा कि आप आमतौर पर MVVM में करते हैं)

तो मैं रेखा से ऊपर और इस प्रकार मेरी कोड के पीछे जोड़ने के रूप में बदलने के लिए है:

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     Text = "Initial Text"; 
     DataContext = this; 
    } 
    private string _Text; 
    public string Text 
    { 
     get { return _Text; } 
     set 
     { 
      if (value != _Text) 
      { 
       _Text = value; 
       NotifyPropertyChanged("Text"); 
      } 
     } 
    } 

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
    { 
     Text = "clicked"; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
} 

न तो "प्रारंभिक पाठ" और न ही "क्लिक किया गया" प्रदर्शित होता है ... कभी भी। तो मेरा सवाल यह है कि एक विभाग को कैसे कार्यान्वित किया जाए। संपत्ति का उपयोग

<uc:MyUserControl1 MyTextProperty="{Binding Text}"/> 

के साथ सही ढंग से उपयोग किया जा सकता है? मेरी मदद करने के लिए धन्यवाद।

उत्तर

22

Text संपत्ति MainWindow UserControl के नहीं की DataContext पर स्थित है।

तो इस में इस लाइन <uc:MyUserControl1 MyTextProperty="{Binding Text}"/> बदलने के लिए:

<uc:MyUserControl1 MyTextProperty="{Binding Text, ElementName=MyMainWindow}"/> 

कौन सा बाइंडिंग बता देगा कि आप पाठ स्थित तत्व के बारे में बात कर रहे हैं आप में MainWindow। बेशक, के बाद से इस उदाहरण में मैं ElementName इस्तेमाल किया है, तो आप नाम अपने विंडो MyMainWindow करना चाहते हैं ... जा रहे हैं

तो अपने MainWindow से जोड़ें: यदि आप इसके बजाय का नाम नहीं हैं

<Window Name="MyMainWindow" ..... /> 

अपने खिड़की, आप RelativeSource FindAncestor इस तरह बंधन का उपयोग कर सकते हैं:

<wpfApplication6:MyUserControl1 MyTextProperty="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"/> 

दोनों तरीकों में, आप संपत्ति विंडो के DataContext के पास 'टेक्स्ट' नाम खोजने के लिए पूछ रहे हैं।

+0

ठीक है, बहुत बहुत धन्यवाद! आम तौर पर मैं एक व्यूमोडेल का उपयोग करता हूं, जिसे मैंने 'DataContext = new MyViewModel() {text = "foo"}' जैसे कोड में सेट किया है। क्या आप विस्तारित कर सकते हैं कि बाध्यकारी कैसे सेट किया जा सकता है? –

+1

मेरा उत्तर अपडेट किया गया, और याद रखें, MyViewModel को 'INotifyPropertyChanged' लागू करना चाहिए यदि टेक्स्ट' निर्भरता प्रॉपर्टी नहीं है। – Blachshma

+0

फिर से धन्यवाद। आपका अपडेट विंडो के लिए दृश्य पेड़ की खोज करता है।लेकिन DataContext के लिए बाध्यकारी कैसे करें, जो मेरा नियंत्रण नहीं है लेकिन एक 'साधारण' वर्ग जो INotifyProperty लागू करता है और मुख्यविंडो के लिए डेटाकॉन्टेक्स्ट के रूप में उपयोग किया जाता है? 'पूर्वज टाइप = MyViewModel' दुर्भाग्य से काम नहीं करेगा ... –