0

コントロールスタイルからコントロールで定義されたプロパティにプロパティをバインドしようとしています。コントロールはTextBoxを継承し、ChangeTextBoxWithRangeUnitsと呼ばれます。作成したValidationRuleクラスからそれらにバインドしようとしています。これが私がテキストを検証しようとしている場所のセッターです

 <Setter Property="Text">
        <Setter.Value>
            <Binding RelativeSource="{RelativeSource Self}"
                     Path="Text"
                     NotifyOnValidationError="True">
                <Binding.ValidationRules>
                    <basic:DoubleValidationRule>
                        <basic:DoubleValidationRule.MinMaxDependencyObject>
                            <basic:MinMaxDependencyObject Minimum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithRangeUnits}}, Path=MinimumValue}"
                                                          Maximum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithRangeUnits}}, Path=MaximumValue}" />
                        </basic:DoubleValidationRule.MinMaxDependencyObject>
                    </basic:DoubleValidationRule>
                </Binding.ValidationRules>
            </Binding>
        </Setter.Value>
    </Setter>

ソースバインディングが見つからないと表示される理由がわかりません。エラーは次のとおりです。

System.Windows.Dataエラー:4:参照'RelativeSource FindAncestor、AncestorType ='Frasca.Simplicity.Controls.UnitControls.ChangeTextBoxWithRangeUnits'、AncestorLevel='1''でバインドするためのソースが見つかりません。BindingExpression:Path = MinimumValue; DataItem = null; ターゲット要素は'MinMaxDependencyObject'(HashCode = 16201505); ターゲットプロパティは「最小」(タイプ「ダブル」)です

完全なXAMLを編集する

 <Style x:Key="ChangeTextBoxWithRangeUnits"
       TargetType="{x:Type local:ChangeTextBoxWithRangeUnits}"
       BasedOn="{StaticResource {x:Type TextBox}}">
    <Setter Property="Validation.ErrorTemplate"
            Value="{x:Null}" />
    <Setter Property="Height"
            Value="64" />
    <Setter Property="FontSize"
            Value="22" />
    <Setter Property="Margin"
            Value="5" />
    <Setter Property="Background"
            Value="LightGray" />
    <Setter Property="BorderThickness"
            Value="0" />
    <Setter Property="KeyboardNavigation.TabNavigation"
            Value="None" />
    <Setter Property="AllowDrop"
            Value="true" />
    <Setter Property="ScrollViewer.PanningMode"
            Value="VerticalFirst" />
    <Setter Property="Stylus.IsFlicksEnabled"
            Value="False" />
    <Setter Property="Text">
        <Setter.Value>
            <Binding RelativeSource="{RelativeSource Self}"
                     Path="Text"
                     NotifyOnValidationError="True">
                <Binding.ValidationRules>
                    <basic:DoubleValidationRule>
                        <basic:DoubleValidationRule.MinMaxDependencyObject>
                            <basic:MinMaxDependencyObject Minimum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithRangeUnits}}, Path=MinimumValue}"
                                                          Maximum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithRangeUnits}}, Path=MaximumValue}" />
                        </basic:DoubleValidationRule.MinMaxDependencyObject>
                    </basic:DoubleValidationRule>
                </Binding.ValidationRules>
            </Binding>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ChangeTextBoxWithUnits}">
                <Grid>
                    <Border Name="bg"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Width="{TemplateBinding Width}"
                            CornerRadius="15"
                            SnapsToDevicePixels="true">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="3*" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="2*" />
                            </Grid.RowDefinitions>

                            <StackPanel Orientation="Horizontal"
                                        Grid.Row="0"
                                        Name="mValueStackPanel"
                                        VerticalAlignment="Bottom"
                                        HorizontalAlignment="Center">
                                <ScrollViewer x:Name="PART_ContentHost"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                                <TextBox Name="PART_UnitTextBlock"
                                         Style="{DynamicResource InlineTextBox}"
                                         Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithUnits}}, Path=Units}"
                                         FontSize="14"
                                         Margin="3,0,0,0"
                                         Foreground="{TemplateBinding Foreground}" />
                            </StackPanel>

                            <StackPanel Orientation="Horizontal"
                                        Grid.Row="2"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Top">
                                <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithUnits}}, Path=Label}"
                                           FontSize="14"
                                           Foreground="{TemplateBinding Foreground}" />
                            </StackPanel>

                            <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithUnits}}, Path=DisabledText}"
                                       Foreground="{TemplateBinding Foreground}"
                                       Grid.Row="0"
                                       FontSize="14"
                                       HorizontalAlignment="Center"
                                       VerticalAlignment="Bottom"
                                       Visibility="Collapsed"
                                       x:Name="mDisabledTextBlock" />

                            <!-- Horizontal line -->
                            <Rectangle Height="1"
                                       Margin="10,0"
                                       Grid.Row="1"
                                       Opacity="0.15"
                                       SnapsToDevicePixels="True"
                                       Fill="{TemplateBinding Foreground}" />

                            <!-- Object which flashes when the textbox is selected -->
                            <Border Grid.RowSpan="3"
                                    Background="White"
                                    Name="FlashObject"
                                    CornerRadius="15"
                                    Opacity="0">
                                <Border.Effect>
                                    <BlurEffect Radius="20" />
                                </Border.Effect>
                            </Border>

                            <!-- Object which flashes when the textbox has a validation error-->
                            <Border Grid.RowSpan="3"
                                    Grid.ColumnSpan="2"
                                    Background="Red"
                                    Name="ErrorFlashObject"
                                    CornerRadius="15"
                                    Opacity="0">
                                <Border.Effect>
                                    <BlurEffect Radius="20" />
                                </Border.Effect>
                            </Border>
                        </Grid>
                    </Border>

                    <!-- Object which glows when the user makes a change to the text value. -->
                    <Border Width="{Binding ElementName=bg, Path=ActualWidth}"
                            Height="{Binding ElementName=bg, Path=ActualHeight}"
                            CornerRadius="15"
                            Background="#FFF066"
                            Name="ChangeGlowObject"
                            Panel.ZIndex="-1"
                            Visibility="Collapsed">
                        <Border.Effect>
                            <BlurEffect Radius="20" />
                        </Border.Effect>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="HasChangedValue"
                                       Value="True" />
                            <Condition Property="IsEnabled"
                                       Value="True" />
                        </MultiTrigger.Conditions>
                        <Setter Property="Visibility"
                                TargetName="ChangeGlowObject"
                                Value="Visible" />
                    </MultiTrigger>
                    <Trigger Property="IsEnabled"
                             Value="False">
                        <Setter Property="Background"
                                Value="#686868" />
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsEnabled"
                                       Value="False" />
                            <!--<Condition Property="ShowTextWhenDisabled"
                                       Value="False" />-->
                        </MultiTrigger.Conditions>
                        <Setter Property="Visibility"
                                TargetName="mDisabledTextBlock"
                                Value="Visible" />
                        <Setter Property="Visibility"
                                TargetName="mValueStackPanel"
                                Value="Collapsed" />
                    </MultiTrigger>

                    <!-- trigger to flash the object when the textbox has an error -->
                    <Trigger Property="Validation.HasError"
                             Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation BeginTime="00:00:00"
                                                     Duration="00:00:00.2"
                                                     From="0"
                                                     To="1"
                                                     Storyboard.TargetName="ErrorFlashObject"
                                                     Storyboard.TargetProperty="Opacity">
                                        <DoubleAnimation.EasingFunction>
                                            <PowerEase Power="2"
                                                       EasingMode="EaseIn" />
                                        </DoubleAnimation.EasingFunction>
                                    </DoubleAnimation>
                                    <DoubleAnimation BeginTime="00:00:00.2"
                                                     Duration="00:00:00.5"
                                                     From="1"
                                                     To="0"
                                                     Storyboard.TargetName="ErrorFlashObject"
                                                     Storyboard.TargetProperty="Opacity">
                                        <DoubleAnimation.EasingFunction>
                                            <PowerEase Power="2"
                                                       EasingMode="EaseIn" />
                                        </DoubleAnimation.EasingFunction>
                                    </DoubleAnimation>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                    </Trigger>

                    <!-- trigger to flash the object when the textbox is selected -->
                    <EventTrigger RoutedEvent="FocusManager.GotFocus">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation BeginTime="00:00:00"
                                                 Duration="00:00:00.2"
                                                 From="0"
                                                 To="1"
                                                 Storyboard.TargetName="FlashObject"
                                                 Storyboard.TargetProperty="Opacity">
                                    <DoubleAnimation.EasingFunction>
                                        <PowerEase Power="2"
                                                   EasingMode="EaseIn" />
                                    </DoubleAnimation.EasingFunction>
                                </DoubleAnimation>
                                <DoubleAnimation BeginTime="00:00:00.2"
                                                 Duration="00:00:00.5"
                                                 From="1"
                                                 To="0"
                                                 Storyboard.TargetName="FlashObject"
                                                 Storyboard.TargetProperty="Opacity">
                                    <DoubleAnimation.EasingFunction>
                                        <PowerEase Power="2"
                                                   EasingMode="EaseIn" />
                                    </DoubleAnimation.EasingFunction>
                                </DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
4

1 に答える 1

1

RelativeSourceバインディングは XML をたどるのではなく、Visual Treeをたどります。つまり、バインドしている要素がそのツリー内にある場合にのみ使用できます。

この場合、yourDoubleValidationRuleはUIElement ではなく、ビジュアル ツリーにもないためRelativeSouceこのルールのバインディングは失敗します。

残念ながら、 の実装や目的を知らDoubleValidationRule.MinMaxDependencyObjectなければ、何をすべきかを判断するのは困難です。検証ルールの実装を変更することで、この制限を回避できる場合があります。

機能する1つの方法は、ツリー内の要素をそのx:Name値で参照できることです

Minimum="{Binding MinimumValue, ElementName=TheMinimumTarget}

しかし、これはおそらく、を使用してこれを行うことができないことを意味します。これはStyle、使用するたびに (おそらく) フォームの異なる要素にバインドされるためです。


あなたの編集を見て... ワット?検証規則を添付するために、コントロールのテキストをコントロールのテキストにバインドしていますか? それは… 私も知りません。

コントロールをサブクラス化して検証ロジックを追加し (たとえば、Text 依存関係プロパティのプロパティ メタデータをオーバーライドする)、テンプレートをこの新しい型に適用することをお勧めします。

于 2013-01-08T16:36:31.620 に答える