1

説明: カスタム コンテンツ コントロールがあり、依存関係プロパティを介していくつかの外部設定を有効にしようとしています。基本的に、これは 2 つのグリッド行を持つデコレータ パネルです。上の行はヘッダー、下の行はコンテンツです (経由ContentPresenter)。

(TemplateBinding を介して) テンプレートにバインドされている 3 つの項目がありますHeaderHeight(TextSizeそれぞれHeaderに適切な型の依存関係プロパティがあります)。

問題: 2 つのバインディングは (設計時でも) 完全に機能しますが、3 つ目のバインディングは機能しません。FontSize="{TemplateBinding TextSize}"Text="{TemplateBinding Header}"バインディングは機能しますが、は<RowDefinition Height="{TemplateBinding HeaderHeight}" /> 機能しません

HeaderHeight プロパティをどの値に設定しても、グリッドは行の高さを 50/50 に分割します。DP メタデータからデフォルト値を取得することさえありません。

質問: このシナリオの問題点は何ですか? 他の 2 つのバインディングは問題なく動作するのに、これはバインディングがまったくないかのように動作するのはなぜですか?

注:コンストラクター を設定DataContext = thisして に置き換える{TemplateBinding HeaderHeight}{Binding HeaderHeight}、問題はなくなり、意図したとおりに動作します。しかし、他のバインディングを機能させるために同じことをする必要がない理由を知りたいです。

XAML (テーマ/Generic.xaml):

<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>

コンテンツ コントロール (C#):

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>
4

2 に答える 2

0

残念ながら、あなたがやろうとしていることは、単一のデータバインディング以上のものを必要としているようです。 RowDefinitionはFrameworkElementのサブクラスではなく、 MSDN Silverlightデータバインディングドキュメントで指定されている他のどの基準とも一致しないため、バインディングのターゲットとして使用することはできません。

やりたいことは可能ですが、残念ながらもう少しコードが必要です。

まず、メイングリッド(私はそれと呼んでいmainGridます)のフィールドをKaiPanelクラスに追加します。次に、このクラスのメソッドをオーバーライドして、テンプレートからOnApplyTemplateメインを取得し、フィールドにメインを保持します。GridmainGrid

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

これは、グリッドの最初の行の高さを更新するメソッドを呼び出します。その方法は次のとおりです。

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

OnApplyTemplateDPが設定された後に呼び出されるかどうかは100%確信が持てないことを認めます。これは事実のようです(簡単なテストでこれを確認したようです)が、これをバックアップするために私が見つけたのは、Silverlightフォーラムへのこの投稿だけでした。そうでない場合は、このメソッドHeaderHeightも呼び出すDPにPropertyChangedCallbackを登録する必要があります。SetHeaderRowHeight

http://forums.silverlight.net/forums/t/76992.aspx#183089も参照してください。

于 2011-06-26T21:11:31.863 に答える