विवरण: मेरे पास कस्टम सामग्री नियंत्रण है और मैं निर्भरता गुणों के माध्यम से कुछ बाहरी सेटिंग्स को सक्षम करने का प्रयास कर रहा हूं। मूल रूप से यह दो ग्रिड पंक्तियों वाला एक डेकोरेटर पैनल है, ऊपरी एक शीर्षलेख है, निचला वाला सामग्री है (ContentPresenter के माध्यम से)।

ऐसे 3 आइटम हैं जो टेम्पलेट से बंधे हैं (टेम्पलेट बाइंडिंग के माध्यम से), HeaderHeight, TextSize और Header (उनमें से प्रत्येक में उपयुक्त प्रकार की निर्भरता संपत्ति है)।

समस्या: जबकि दो बाइंडिंग पूरी तरह से काम करती हैं (डिजाइन-टाइम में भी), तीसरा नहीं। FontSize="{TemplateBinding TextSize}" और Text="{TemplateBinding Header}" बाइंडिंग काम करते हैं, लेकिन <RowDefinition Height="{TemplateBinding HeaderHeight}" /> काम नहीं करते

ग्रिड पंक्तियों की ऊंचाई 50/50 को विभाजित करता है, इससे कोई फर्क नहीं पड़ता कि मैंने हेडरहाइट संपत्ति को किस मूल्य पर सेट किया है। यह डीपी मेटाडेटा से डिफ़ॉल्ट मान भी नहीं लेता है।

प्रश्न: इस परिदृश्य में समस्या क्या है? अन्य दो बाइंडिंग बिना किसी समस्या के क्यों काम करते हैं और यह ऐसा व्यवहार करता है जैसे कि कोई बंधन ही नहीं है?

नोट: अगर मैं कंस्ट्रक्टर में DataContext = this सेट करता हूं और {TemplateBinding HeaderHeight} को {Binding HeaderHeight} से बदल देता हूं, तो समस्या गायब हो जाती है और यह इरादा के अनुसार काम करता है। लेकिन मैं जानना चाहता हूं कि उन्हें काम करने के लिए मुझे अन्य बाइंडिंग के साथ ऐसा करने की ज़रूरत क्यों नहीं है।

एक्सएएमएल (थीम्स/जेनेरिक.एक्सएमएल):

<Style TargetType="local:KaiPanel">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:KaiPanel">
                <Grid x:Name="LayoutRoot">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="{TemplateBinding HeaderHeight}" />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <Grid Grid.Row="0">
                        <Border>
                            <TextBlock FontSize="{TemplateBinding TextSize}" 
                                       Text="{TemplateBinding Header}" />
                        </Border>
                    </Grid>

                    <Grid Grid.Row="1">
                        <Border>
                            <ContentPresenter />
                        </Border>
                    </Grid>

                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

सामग्री नियंत्रण (सी#):

public class KaiPanel : ContentControl
{
    public KaiPanel()
    {
        this.DefaultStyleKey = typeof(KaiPanel);
    }

    public static readonly DependencyProperty TextSizeProperty =
        DependencyProperty.Register("TextSize", typeof(double), typeof(KaiPanel), new PropertyMetadata(15.0));

    public double TextSize
    {
        get { return (double)GetValue(TextSizeProperty); }
        set { SetValue(TextSizeProperty, value); }
    }

    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register("Header", typeof(String), typeof(KaiPanel), new PropertyMetadata(""));

    public String Header
    {
        get { return (String)GetValue(HeaderProperty); }
        set { SetValue(HeaderProperty, value); }
    }

    public static readonly DependencyProperty HeaderHeightProperty =
        DependencyProperty.Register("HeaderHeight", typeof(GridLength), typeof(KaiPanel), new PropertyMetadata(new GridLength(40)));

    public GridLength HeaderHeight
    {
        get { return (GridLength)GetValue(HeaderHeightProperty); }
        set { SetValue(HeaderHeightProperty, value); }
    }
}

कस्टम नियंत्रण उपयोग (XAML):

<UserControl ...>

    <Grid x:Name="LayoutRoot">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <StackPanel x:Name="buttonsStackPanel" Grid.Column="0" VerticalAlignment="Center">
            <!-- Some buttons here -->
        </StackPanel>

        <Grid Grid.Column="1">
            <controls:KaiPanel x:Name="contentPanel">
                <navigation:Frame x:Name="contentFrame" Source="KP">
                    <navigation:Frame.UriMapper>
                        <uriMapper:UriMapper>
                            <uriMapper:UriMapping Uri="KP" MappedUri="/Views/Kornelijepetak.xaml" />
                            <uriMapper:UriMapping Uri="KAI" MappedUri="/Views/KaiNetwork.xaml" />
                        </uriMapper:UriMapper>
                    </navigation:Frame.UriMapper>
                </navigation:Frame>
            </controls:KaiPanel>
        </Grid>
    </Grid>
</UserControl>
1
Kornelije Petak 26 जून 2011, 17:19
क्या आपके पास वास्तव में KaiPanel का उपयोग करने वाले आपके Xaml का उदाहरण है ताकि हम समस्या को पुन: उत्पन्न कर सकें? अब तक दिखाया गया सब कुछ ठीक दिखता है, लेकिन किसी चीज़ को तोड़ने के लिए केवल एक छोटी सी जानकारी की आवश्यकता होती है।
 – 
Gone Coding
26 जून 2011, 22:32
कोड अपडेट किया है, लेकिन इससे कोई फर्क नहीं पड़ता। यदि आप एक भी टैग लगाते हैं तो भी यह काम नहीं करता है। इसे डीपी से डिफ़ॉल्ट मान लेना चाहिए, लेकिन ऐसा नहीं है। अलग सामग्री को अंदर रखने की कोशिश की, लेकिन इससे कोई फर्क नहीं पड़ता - यह हमेशा एक जैसा व्यवहार करता है: 50/50।
 – 
Kornelije Petak
26 जून 2011, 23:25

2 जवाब

सबसे बढ़िया उत्तर

अफसोस की बात है कि ऐसा लगता है कि आप जो करने का प्रयास कर रहे हैं, उसके लिए केवल एक डेटा बाइंडिंग से अधिक की आवश्यकता है। RowDefinition FrameworkElement का उपवर्ग नहीं है, और यह MSDN सिल्वरलाइट डेटा बाइंडिंग दस्तावेज़ीकरण, इसलिए इसे बाइंडिंग के लक्ष्य के रूप में उपयोग नहीं किया जा सकता है।

आप जो करना चाहते हैं वह संभव है, लेकिन दुर्भाग्य से इसमें थोड़ा और कोड शामिल है।

सबसे पहले, अपनी KaiPanel कक्षा में मुख्य ग्रिड (मैंने इसे mainGrid कहा है) के लिए एक फ़ील्ड जोड़ें। फिर, टेम्प्लेट से मुख्य Grid को हथियाने के लिए इस कक्षा में OnApplyTemplate विधि को ओवरराइड करें और अपने mainGrid फ़ील्ड में इसका संदर्भ रखें:

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        mainGrid = GetTemplateChild("LayoutRoot") as Grid;
        SetHeaderRowHeight();
    }

यह एक विधि को कॉल करता है जो ग्रिड की पहली पंक्ति की ऊंचाई को अद्यतन करता है। वह विधि इस प्रकार है:

    private void SetHeaderRowHeight()
    {
        if (mainGrid != null)
        {
            mainGrid.RowDefinitions[0].Height = HeaderHeight;
        }
    }

मैं मानता हूँ कि मुझे 100% यकीन नहीं है कि OnApplyTemplate को डीपी सेट होने के बाद बुलाया जाता है। ऐसा लगता है कि यह मामला है (इसकी पुष्टि करने के लिए एक त्वरित परीक्षण लग रहा था), लेकिन मुझे इसका समर्थन करने के लिए केवल सिल्वरलाइट फ़ोरम पर यह पोस्ट। यदि आप पाते हैं कि ऐसा नहीं है, तो आपको HeaderHeight DP पर एक PropertyChangedCallback पंजीकृत करना होगा जो इस SetHeaderRowHeight विधि को भी कॉल करेगा।

यह भी देखें http://forums.silverlight.net/forums/t/76992.aspx #183089.

0
Luke Woodward 27 जून 2011, 01:11
आप कहते हैं कि इसका उपयोग बाइंडिंग में नहीं किया जा सकता है, फिर भी यह सामान्य बाइंडिंग (टेम्पलेट बाइंडिंग नहीं) में काम करता है। मेरा नोट फिर से जांचें। यदि डेटाकॉन्टेक्स्ट = यह एक कन्स्ट्रक्टर में सेट है, और टेम्पलेट में यदि मैं सेट करता हूं: {टेम्पलेट बाइंडिंग हैडरहाइट} के बजाय {बाइंडिंग हेडरहाइट}, तो यह काम करता है। बहुत अजीब व्यवहार। मेरे पास एक और नियंत्रण है जो टेम्पलेट बाइंडिंग के साथ भी काम करता है, जो इसे और भी अजीब बनाता है।
 – 
Kornelije Petak
27 जून 2011, 08:31
सुधार: मैंने अब अपने दूसरे नियंत्रण को देखा है। यह टेम्पलेट बाध्यकारी के साथ काम नहीं करता है, लेकिन यह सामान्य बाध्यकारी के साथ करता है (डेटाकॉन्टेक्स्ट नियंत्रण में सेट के साथ)।
 – 
Kornelije Petak
27 जून 2011, 08:37

इसके बजाय सापेक्ष स्रोत और टेम्पलेटेड माता-पिता का प्रयोग करें:

<RowDefinition Height="{Binding RelativeSource={RelativeSource TemplatedParent},
 Path=HeaderHeight}" />

यहाँ TemplateBinding और RelativeSource TemplatedParent के बीच का अंतर समझाया गया है: WPF TemplateBinding बनाम RelativeSource TemplatedParent

0
Lord Tasci 21 अप्रैल 2021, 09:42