排除绑定错误4

时间:2011-06-29 00:10:23

标签: c# wpf data-binding

我的代码出现以下绑定错误,我不知道如何对其进行故障排除。绑定由VS生成。我已经尝试添加presentation.tracesources(在下面的代码中),但我得到的输出与以前相同。

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='ClimateSolutions.SuperTB', AncestorLevel='1''. BindingExpression:Path=myName; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='ClimateSolutions.SuperTB', AncestorLevel='1''. BindingExpression:Path=isRequired; DataItem=null; target element is 'SuperTB' (Name='email'); target property is 'NoTarget' (type 'Object')

这是我的XAML:

<TextBox x:Class="ClimateSolutions.SuperTB"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" Height="53" Width="296" FontSize="32"
         xmlns:local="clr-namespace:ClimateSolutions"
xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"

         HorizontalAlignment="Left" Name="Blarg">
<TextBox.Style>
    <Style TargetType="TextBox">
        <Style.Triggers>
            <Trigger Property="Text" Value="">
                <Setter Property="Background">
                    <Setter.Value>
                        <VisualBrush Stretch="None">
                            <VisualBrush.Visual>
                                <TextBlock Foreground="Gray" FontSize="24" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:SuperTB, AncestorLevel=1}, Path=myName, diagnostics:PresentationTraceSources.TraceLevel=High}">
                                </TextBlock>
                            </VisualBrush.Visual>
                        </VisualBrush>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <DataTrigger Binding="{Binding Path=isRequired, RelativeSource={RelativeSource FindAncestor, AncestorType=local:SuperTB, AncestorLevel=1}}" Value="False">
                <Setter Property="Text" Value="100" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</TextBox.Style>

这里是SuperTB的CS:

namespace ClimateSolutions
{
    /// <summary>
    /// Interaction logic for SuperTB.xaml
    /// </summary>
    public partial class SuperTB : TextBox, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String Property)
        {
            var anEvent = this.PropertyChanged;

            if (anEvent != null)
            {
                anEvent(this, new PropertyChangedEventArgs(Property));
            }
        }

        private String MyName = "Unicorns!";

        private static DependencyProperty myNameProperty = DependencyProperty.Register("myName", typeof(String), typeof(SuperTB));
        public String myName
        {
            get { return MyName; }
            set { MyName = value; NotifyPropertyChanged("myName"); }
        }

        DependencyProperty isRequiredProperty = DependencyProperty.Register("isRequired", typeof(Boolean), typeof(SuperTB));

        public Boolean isRequired
        {
            get { return (Boolean)GetValue(isRequiredProperty); }
            set { SetValue(isRequiredProperty, value); }
        }

        public SuperTB()
        {
            InitializeComponent();
            myName = "Unicorns!";
        }
    }
}

2 个答案:

答案 0 :(得分:1)

编辑:我已根据您的评论更新了代码。总而言之,由于这是一个自定义控件,因此只要组件本身满足此需求(排序,使其属性),就不再依赖MVVM模式来构建组件逻辑(因此在组件中使用代码)尽可能多的可绑定)。例如,在更新的代码中,您现在可以绑定默认属性,但您也可以设想在没有值时显示属性以设置用于显示控件名称的前景颜色,等等。


我用原始代码尝试了几件事(包括J cooper提供的解决方案),似乎没什么用。您的代码似乎存在很多问题。

我设法通过使您的文本框成为自定义控件来解决问题。

这是Generic.xaml(控件的可视定义):

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Question_6514447">


<Style TargetType="{x:Type local:SuperTB2}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:SuperTB2}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <TextBox x:Name="PART_Input">
                        <TextBox.Style>
                            <Style TargetType="TextBox">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsRequired}" Value="False">
                                        <Setter Property="Text" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DefaultTextValue}" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </TextBox.Style>
                    </TextBox>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
</ResourceDictionary>

以下是控件背后的代码:

 [TemplatePart(Name = "PART_Input")]
public class SuperTB2 : Control
{
    private TextBox PART_Input;
    static SuperTB2()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(SuperTB2), new FrameworkPropertyMetadata(typeof(SuperTB2)));
    }

    public SuperTB2()
    {
        Loaded += SuperTb2Loaded;
    }
    public override void OnApplyTemplate()
    {
        PART_Input = GetTemplateChild("PART_Input") as TextBox;
        if (PART_Input != null)
        {


            PART_Input.GotFocus += PartInputGotFocus;
            PART_Input.LostFocus += PartInputLostFocus;
        }
    }

    void PartInputLostFocus(object sender, RoutedEventArgs e)
    {
        if (PART_Input.Text == string.Empty)
        {
            PART_Input.Text = Name;
            PART_Input.Foreground = new SolidColorBrush(Colors.Gray);
        }
    }

    void PartInputGotFocus(object sender, RoutedEventArgs e)
    {
        if (PART_Input.Text.Equals(Name))
        {
            PART_Input.Text = string.Empty;
            PART_Input.Foreground = new SolidColorBrush(Colors.Black);

        }
    }

    void SuperTb2Loaded(object sender, RoutedEventArgs e)
    {
        if (PART_Input.Text == string.Empty)
        {
            PART_Input.Text = Name;
            PART_Input.Foreground = new SolidColorBrush(Colors.Gray);
        }
    }

    private static DependencyProperty myNameProperty =
DependencyProperty.Register("MyName", typeof(string), typeof(SuperTB2), new PropertyMetadata("Unicorns !", NameChanged));

    private static void NameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {

    }

    public string MyName
    {
        get { return (string)GetValue(myNameProperty); }
        set { SetValue(myNameProperty, value); }
    }
    DependencyProperty isRequiredProperty =
        DependencyProperty.Register("IsRequired", typeof(bool), typeof(SuperTB2), new PropertyMetadata(false, IsReqChanged));

    private static void IsReqChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {

    }

    public bool IsRequired
    {
        get { return (bool)GetValue(isRequiredProperty); }
        set { SetValue(isRequiredProperty, value); }
    }



    public string DefaultTextValue
    {
        get { return (string)GetValue(DefaultTextValueProperty); }
        set { SetValue(DefaultTextValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for DefaultTextValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DefaultTextValueProperty =
        DependencyProperty.Register("DefaultTextValue", typeof(string), typeof(SuperTB2), new UIPropertyMetadata("100"));


}

使用该组件的一个例子:

<Grid>
    <StackPanel>
        <Question_6514447:SuperTB2 x:Name="FirstName" IsRequired="true" DefaultTextValue="200"/>
    </StackPanel>
</Grid>

使用此更新代码,我认为您可以实现所需的几乎所有行为!

希望这会有所帮助!

答案 1 :(得分:0)

不要在绑定表达式中使用相对源。相对源用于访问元素树中较高的元素。好像你在对象继承方面使用它。

<Trigger Property="Text" Value="">
    <Setter Property="Background">
        <Setter.Value>
            <VisualBrush Stretch="None">
                <VisualBrush.Visual>
                    <TextBlock Foreground="Gray" FontSize="24" Text="{Binding Path=myName, diagnostics:PresentationTraceSources.TraceLevel=High}">
                    </TextBlock>
                </VisualBrush.Visual>
            </VisualBrush>
        </Setter.Value>
    </Setter>
</Trigger>
<DataTrigger Binding="{Binding Path=isRequired}" Value="False">
    <Setter Property="Text" Value="100" />
</DataTrigger>