3

フォームで使用されるカスタム コントロールがあります。このコントロールは、ラベルとテキスト ボックスを組み合わせたものです。フォームが読み取り専用モードの場合、コントロールはテキスト ボックスの代わりにラベルを表示するように変更されます。これを行うために、次のように、コントロールのコンテンツ テンプレートを定義しました。

<Style TargetType="{x:Type Controls:FormFieldControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="200"/>
                        <ColumnDefinition Width="200"/>
                    </Grid.ColumnDefinitions>

                    <AdornerDecorator Grid.Column="1"
                                      Visibility="{Binding RelativeSource={RelativeSource AncestorType=Controls:FormFieldControl}, 
                                                   Path=IsReadOnly, 
                                                   Converter={StaticResource BooleanToInverseVisibilityConverter}, 
                                                   Mode=OneWay}">
                        <ContentPresenter Name="ContentPresenter" />
                    </AdornerDecorator>

                    <AdornerDecorator Grid.Column="1"
                                      Visibility="{Binding RelativeSource={RelativeSource AncestorType=FormFieldControl}, 
                                      Path=IsReadOnly, Converter={StaticResource BooleanToVisibilityConverter}, 
                                      Mode=OneWay}">
                        <ContentPresenter Name="ReadOnlyContentPresenter" />
                    </AdornerDecorator>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

ReadOnlyContentPresenterのコンテンツは、次のスタイルが適用されたラベルです。

<Style x:Key="ReadOnlyFormFieldControl" TargetType="{x:Type Label}">
    <Setter Property="Width" Value="400" />
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Controls:FormFieldControl}, 
                               Path=ReadOnlyWidth, 
                               Converter={StaticResource IsSetConverter}}"
                     Value="True">
            <Setter Property="Width" 
                    Value="{Binding RelativeSource={RelativeSource AncestorType=Controls:FormFieldControl}, Path=ReadOnlyWidth}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

これは約 80 個のコントロールに対しては正常に機能しますが、さらにコントロールをフォームに追加すると、ラベル スタイルのバインディングがソースを見つけられません (エラー 4):

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='MyProject.Controls.FormFieldControl', AncestorLevel='1''. BindingExpression:Path=ReadOnlyWidth; DataItem=null; target element is 'Label' (Name=''); target property is 'ReadOnlyWidth' (type 'Double?')

コントロールの編集可能な部分に適用されたスタイルでも同じことが起こります。コントロール番号のコードを移動すると、問題は処理されているコントロールの量に関連していると思います。81(不合格) 管理番号の真上 80(稼働中)、管理番号のバインディング。81は現在動作していますが、制御されているものはありません。80 失敗します。いくつかのコントロールに対してこれを行いましたが、動作は一貫しています。

AdornerDecorator正確にどのように機能するかについてはまだ明確ではありません。調査中に、アドナーレイヤーに144を超えるアドナーを持つ問題について言及しているこの質問AdornerDecoratorを見つけたので、コード内の 's を削除して、バインディングの問題を見つけました。それはコントロール番号に起こっていました。81 以上がすべてのFormFieldControl's に発生しています。

最後に、コントロール テンプレートでContentControlの代わりにを試してみることにしました。ContentPresenterこれは、フォーム内のすべてのコントロールに対して正常に機能します。ContentPresenterこれは の軽量な形式でContentControlあり、それよりもコンテンツ テンプレート内で使用するのに適していることはわかっていContentControlます。ContentPresenterただし、を使用するとバインディングが失敗し、を使用するとバインディングが機能する理由がよくわかりませんContentControl

また、限られたセットのコントロールしか機能せず、AdornerDecorator を使用しない場合、いずれのコントロールもバインディング ソースを見つけられないことも奇妙に感じます。

誰かが似たようなものに出くわしましたか? 私が間違っていることはありContentPresenterますか?または、これが予想される動作である場合、誰かが何が起こっているのかを理解するのを手伝ってくれますか?

どんなアイデアでも大歓迎です。

4

2 に答える 2

0

ラベルがテキストボックスの内容を表示するだけなのか、カスタムラベルを表示する必要があるのか​​ はあなたの質問からは明らかではありませんが、前者の場合はIsReadOnly、すでに述べたようにプロパティを使用する必要があると思います.

ControlTemplateの背景と境界線を非表示にして読み取り専用にするカスタムを定義して、TextBox単なる のように見せることができますLabel

次の簡単な例を試してください。

<StackPanel>
    <StackPanel.Resources>
        <Style x:Key="{x:Type TextBox}"
               TargetType="{x:Type TextBoxBase}">
            <Setter Property="SnapsToDevicePixels"
                    Value="True" />
            <Setter Property="OverridesDefaultStyle"
                    Value="True" />
            <Setter Property="KeyboardNavigation.TabNavigation"
                    Value="None" />
            <Setter Property="FocusVisualStyle"
                    Value="{x:Null}" />
            <Setter Property="MinWidth"
                    Value="120" />
            <Setter Property="MinHeight"
                    Value="20" />
            <Setter Property="AllowDrop"
                    Value="true" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBoxBase}">
                        <Border Name="Border"
                                CornerRadius="2"
                                Padding="2"
                                Background="AliceBlue"
                                BorderBrush="Black"
                                BorderThickness="1">
                            <ScrollViewer Margin="0"
                                          x:Name="PART_ContentHost" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsReadOnly"
                                     Value="True">
                                <Setter TargetName="Border"
                                        Property="Background"
                                        Value="Transparent" />
                                <Setter TargetName="Border"
                                        Property="BorderBrush"
                                        Value="Transparent" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </StackPanel.Resources>
    <TextBox Margin="50,25"
             Name="tb" />

    <Button Content="Switch modes"
            Margin="50,25"
            Click="Button_Click" />
</StackPanel>

読み取り専用モードに切り替えるには、次のボタン クリック ハンドラが必要です。

private void Button_Click(object sender, RoutedEventArgs e)
{
    tb.IsReadOnly = !tb.IsReadOnly;
}

TextBoxが編集可能な場合の結果は次のとおりです。

ここに画像の説明を入力

これは、TextBox読み取り専用の場合の外観です。

ここに画像の説明を入力

于 2012-11-27T17:01:40.937 に答える