2013-01-08 138 views
0

我試圖綁定到我的控件樣式屬性到控件中定義的屬性。該控件繼承自TextBox並被稱爲ChangeTextBoxWithRangeUnits。我試圖從我創建的ValidationRule類綁定到它們。這裏是哪裏,我試圖驗證WPF數據驗證失敗綁定

<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 Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='Frasca.Simplicity.Controls.UnitControls.ChangeTextBoxWithRangeUnits', AncestorLevel='1''. BindingExpression:Path=MinimumValue; DataItem=null; target element is 'MinMaxDependencyObject' (HashCode=16320155); target property is 'Minimum' (type 'Double')

編輯完成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> 
+0

你可以添加一個完整的XAML例子嗎? – Blachshma

回答

1

RelativeSource綁定不走你的XML,他們走了視覺樹。這意味着只要只有您綁定的元素在該樹內,纔可以使用

在這種情況下,您的DoubleValidationRule一個的UIElement,這是不在可視化樹,所以這個規則RelativeSouce綁定將失敗。

不幸的是,不知道你的DoubleValidationRule.MinMaxDependencyObject的實施或目的,它很難說你應該做什麼。您可以通過更改驗證規則的實施來解決此限制。將工作

的一種方法是,你可以通過它的x:Name

Minimum="{Binding MinimumValue, ElementName=TheMinimumTarget} 

是指元件樹但是,這可能意味着使用Style你不能這樣做,因爲每次使用(可能)被綁定到表單上的其他元素。


看着你的編輯...笏?您將控件的文本綁定到控件的文本以附加驗證規則?那是......我什至不是。

我建議子控制爲了添加驗證邏輯(例如,覆蓋文本依賴項屬性的屬性元數據),然後將您的模板應用到此新類型。

+0

對,這是一種風格,所以我不能申請一個名字。 MinMaxDependencyObject是一個簡單的類,它繼承了具有Minimum和Maximum值的DependencyObject。它的唯一目的是讓我可以使用綁定的DoubleValidationRule。你有什麼建議嗎?謝謝。 – user842818