简体   繁体   中英

Got “XPath can't bind to non-XML object” when try to bind with my control, but works with TextBox

I've the custom control with 3 DependencyProperty:

<UserControl x:Class="WpfDemoApp.NewsCard" [...]>
<Border BorderThickness="10" CornerRadius="10" BorderBrush="Wheat" Background="Wheat" Margin="3">
    <StackPanel Background="Wheat">
        <TextBlock Text="{Binding Date}" TextAlignment="Left"/>
        <TextBlock Text="{Binding Title}" FontWeight="Bold" TextAlignment="Left" TextWrapping="Wrap" Margin="0, 3, 0, 3"/>
        <TextBlock Text="Description:"  FontWeight="Bold" />
        <TextBlock Text="{Binding Text}" TextAlignment="Justify" TextWrapping="Wrap" TextTrimming="WordEllipsis"/>
    </StackPanel>
</Border>
</UserControl>

In the c# code:

public partial class NewsCard : UserControl
{
    public NewsCard()
    {
        InitializeComponent();
        DataContext = this;
    }

    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }
    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register("Title", typeof(string), typeof(NewsCard), new UIPropertyMetadata("<title>"));

    public string Date
    {
        get { return (string)GetValue(DateProperty); }
        set { SetValue(DateProperty, value); }
    }
    public static readonly DependencyProperty DateProperty =
        DependencyProperty.Register("Date", typeof(string), typeof(NewsCard), new UIPropertyMetadata("01.01.1970"));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(NewsCard), new UIPropertyMetadata("<text>"));   
}

I'm using the following XML Data Provider:

<XmlDataProvider x:Key="RssData" XPath="//item" Source="http://www.engadget.com/rss.xml"/>

And try to use it the main window XAML file:

<demo:NewsCard Title="{Binding Source=RssData, XPath=title[1]}" Date="{Binding Source=RssData, XPath=pubDate[1]}" Text="{Binding Source=RssData, XPath=description[1]}"/>

Got the same error message for all properties:

System.Windows.Data Error: 45 : BindingExpression with XPath cannot bind to non-XML object.; XPath='title[1]' BindingExpression:Path=/InnerText; DataItem='String' (HashCode=-696447263); target element is 'NewsCard' (Name=''); target property is 'Title' (type 'String') RssData

When I use totally the same binding expression inside Text property of TextBox control everything works fine. What's wrong when I try to use it with my control? Help is very appreciated!

No idea why it would work on a TextBox, but the Binding Source should be specified as StaticResource . Otherwise the source object is just the string "RssData".

Title="{Binding Source={StaticResource RssData}, XPath=title[1]}" 

Finally I found the root of "evil". In my custom component class Context was set to the class self-instance, this prevent XML data to be set as the context for the component. That's why I got "XPath cannot bind to non-XML object", context points to the object itself and since it is not an XML data - using of XPath raise the error.

Hence I removed the following line:

DataContext = this;

from the constructor and set the relative databinding in the XAML file:

[...]
<StackPanel Background="Wheat">
    <TextBlock Text="{Binding Date, RelativeSource={RelativeSource AncestorType={x:Type wpfDemoApp:NewsCard}}}" TextAlignment="Left"/>
    <TextBlock Text="{Binding Title, RelativeSource={RelativeSource AncestorType={x:Type wpfDemoApp:NewsCard}}}" FontWeight="Bold" TextAlignment="Left" TextWrapping="Wrap" Margin="0, 3, 0, 3"/>
    <TextBlock Text="Description:"  FontWeight="Bold" />
    <TextBlock Text="{Binding Text, RelativeSource={RelativeSource AncestorType={x:Type wpfDemoApp:NewsCard}}}" TextAlignment="Justify" TextWrapping="Wrap" TextTrimming="WordEllipsis"/>
</StackPanel>

after these changes the component works as expected.

So, for short:

  • remove explicit Context set in the constructor
  • set RelativeSource binding in the XAML

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM