8
votes

I've been searching for hours on this error that appears in the output window. I'm pretty new to bindings in WPF, so I'm sure there's something I'm missing.

Full text of the error (there is one for each binding path, all similar to this one):

System.Windows.Data Error: 39 : BindingExpression path error: 'TestItem' property not found on 'object' ''String' (HashCode=-842352750)'. BindingExpression:Path=TestItem; DataItem='String' (HashCode=-842352750); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

EDIT: Everything seems to work as it should, but I get these errors in the output window.

XAML:

<UserControl>
    <UserControl.Resources>
        <c:MyData x:Key="myDataSource"/>
        <DataTemplate x:Key="image">
            <Image x:Name="TheImage" />
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=PassFail}" Value="PASS">
                    <Setter TargetName="TheImage" Property="Source" Value="Images/accept.png" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=PassFail}" Value="FAIL">
                    <Setter TargetName="TheImage" Property="Source" Value="Images/delete.png" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=PassFail}" Value="WARNING">
                    <Setter TargetName="TheImage" Property="Source" Value="Images/warning.png" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
        <Storyboard x:Key="OnMouseLeftButtonDown1"/>
    </UserControl.Resources>
    <UserControl.DataContext>
        <Binding Source="{StaticResource myDataSource}"/>
    </UserControl.DataContext>
    <ListView Margin="0,94,-4,-7" x:Name="lsvwOutput" ItemsSource="{Binding Source={StaticResource myDataSource}}"  MouseUp="lsvwOutput_MouseUp" FontFamily="Verdana">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Test Item" Width="300"  DisplayMemberBinding="{Binding Path=TestItem}" />
                <GridViewColumn Header="Information" Width="0" DisplayMemberBinding="{Binding Path=Information}"/>
                <GridViewColumn Header="Result" Width="0" DisplayMemberBinding="{Binding Path=PassFail}"/>
                <GridViewColumn Header="Result" CellTemplate="{StaticResource image}" />
            </GridView>
        </ListView.View>
    </ListView
</UserControl>

Code behind:

public class MyData : INotifyPropertyChanged
{
    private string _testitem = "";
    private string _information = "";
    private string _passfail = "";

    public string TestItem {
        get { return _testitem; }
        set
        {
            _testitem = value;
            OnPropertyChanged("TestItem");
        }

    }
    public string Information {
        get { return _information; }
        set
        {
            _information = value;
            OnPropertyChanged("Information");
        }
    }
    public string PassFail {
        get { return _passfail; }
        set
        {
            _passfail = value;
            OnPropertyChanged("PassFail");
        }
    }
    public string Text { get; set; }
2
Why are you setting a non-enumerable object to the ItemsSource?Landern
@Moses I've changed what my ItemsSource was several times now, looking at different examples. I don't have a good understanding what should go there. The code I posed was the last iteration I tried, not necessarily have I would have originally done.isorfir

2 Answers

11
votes

You don't want to set the DataContext on the UserControl. Instead, you want to set it in the scope of the UserControl.

Usually you do this in the constructor of the UserControl. I usually add a line like this:

this.RootElement.DataContext = myData;

Where RootElement is the first sub-element (the Content) of your UserControl (usually a panel like Grid or StackPanel).

In your case it would be:

this.lsvwOutput.DataContext = FindResource("myDataSource");

And makes sure that it's after the InitializeComponent() call.

It's just a question of scoping. You set the datacontext on the root panel of the usercontrol. This is a really non-obvious part of WPF.

UPDATE: As Markus points out below, in the case of a listview, you want to set an array of data, not just a data point. Take that into consideration when setting the DataContext in your constructor.

6
votes

seems like you're binding your listviews itemssource to an object, not an array. is everything working visually? or do you see nothing?

EDIT: what happens if you write instead of:

<c:MyData x:Key="myDataSource"/>

this:

<x:Array x:Key="myDataSource" Type="{x:Type c:MyData}">
  <c:MyData />      
</x:Array>

or any likewise collection definition