विवरण: मेरे पास कस्टम सामग्री नियंत्रण है और मैं निर्भरता गुणों के माध्यम से कुछ बाहरी सेटिंग्स को सक्षम करने का प्रयास कर रहा हूं। मूल रूप से यह दो ग्रिड पंक्तियों वाला एक डेकोरेटर पैनल है, ऊपरी एक शीर्षलेख है, निचला वाला सामग्री है (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>
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.
इसके बजाय सापेक्ष स्रोत और टेम्पलेटेड माता-पिता का प्रयोग करें:
<RowDefinition Height="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=HeaderHeight}" />
यहाँ TemplateBinding और RelativeSource TemplatedParent के बीच का अंतर समझाया गया है: WPF TemplateBinding बनाम RelativeSource TemplatedParent
संबंधित सवाल
जुड़े हुए प्रश्न
नए सवाल
silverlight
सिल्वरलाइट माइक्रोसॉफ्ट के क्रॉस-ब्राउज़र, मीडिया अनुभवों और समृद्ध इंटरैक्टिव अनुप्रयोगों के लिए क्रॉस प्लेटफॉर्म प्लग-इन है।