سؤال

I have a SL5 project where I am trying to data bind a collection to a ItemsControl, I keep getting the error:

BindingExpression path error: 'ItemName' property not found on 'EventViewer.Data.ViewModels.ProductListModel' 'EventViewer.Data.ViewModels.ProductListModel' (HashCode=7414170). BindingExpression: Path='ItemName' DataItem='EventViewer.Data.ViewModels.ProductListModel' (HashCode=7414170); target element is 'System.Windows.Controls.TextBlock' (Name=''); target property is 'Text' (type 'System.String')..
BindingExpression path error: 'Price' property not found on 'EventViewer.Data.ViewModels.ProductListModel' 'EventViewer.Data.ViewModels.ProductListModel' (HashCode=7414170). BindingExpression: Path='Price' DataItem='EventViewer.Data.ViewModels.ProductListModel' (HashCode=7414170); target element is 'System.Windows.Controls.TextBlock' (Name=''); target property is 'Text' (type 'System.String')..
BindingExpression path error: 'Description' property not found on 'EventViewer.Data.ViewModels.ProductListModel' 'EventViewer.Data.ViewModels.ProductListModel' (HashCode=7414170). BindingExpression: Path='Description' DataItem='EventViewer.Data.ViewModels.ProductListModel' (HashCode=7414170); target element is 'System.Windows.Controls.TextBlock' (Name=''); target property is 'Text' (type 'System.String')..

I have these properties in the ProductQtyItem and the databinding appears to be setup correctly. Here is what I have:

The XAML:

<sdk:ChildWindow    
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"   
    xmlns:EventViewer="clr-namespace:EventViewer" 
    xmlns:ViewModels="clr-namespace:EventViewer.Data.ViewModels"    
    xmlns:converters="clr-namespace:EventViewer.Converters"
    x:Class="EventViewer.PurchaseWindow"
    Title="Purchase"  
    HorizontalAlignment="Stretch" 
    VerticalAlignment="Stretch"
    Width="539" Height="550">
    <sdk:ChildWindow.Resources>

        <converters:BooleanVisibilityConverter x:Key="BooleanVisibilityConverter"/>
        <converters:NumericCurrencyConverter x:Key="NumericCurrencyConverter"/>

        <ControlTemplate x:Key="ProductItemTemplate" TargetType="ItemsControl">
            <Grid Margin="3">

                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" VerticalAlignment="Center" 
                           Style="{StaticResource ProductNameTextBlockStyle}"
                           Text="{Binding ItemName, Mode=OneWay}"/>

                <TextBlock Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Center" 
                           Style="{StaticResource ProductPriceTextBlockStyle}"
                           Text="{Binding Price, Converter={StaticResource NumericCurrencyConverter}, Mode=OneWay}" />

                <TextBlock Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center" TextWrapping="Wrap" 
                           Text="{Binding Description, Mode=OneWay}"/>
            </Grid>
        </ControlTemplate>
    </sdk:ChildWindow.Resources>
    <Grid x:Name="LayoutRoot">
        <Grid.DataContext>
            <ViewModels:ProductListModel/>
        </Grid.DataContext>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Viewbox Stretch="Uniform" StretchDirection="DownOnly" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="100" 
            DataContext="{Binding ImageData}">
            <Image Source="{Binding ImagePath, Mode=OneWay}" ImageOpened="Image_ImageOpened"/>
        </Viewbox>

        <ItemsControl 
            HorizontalAlignment="Left" Margin="0,105,0,0" VerticalAlignment="Top" Width="521" Height="377"          
            Template="{StaticResource ProductItemTemplate}" 
            ItemsSource="{Binding ProductQtyItems}"/>

        <Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Grid.Row="1" />
    </Grid>
</sdk:ChildWindow>

The code that is to follow is how I wire up a ProductListModel to the LayoutRoot.DataContext of the above XAML code. So, if I understand things correctly, the binding for the ItemsControl will bind to the List ProductQtyItems of ProductListModel. So, won't the templates have the datasource set to ProductQtyItem? What am I missing?


Here is the rest of the code:

And this is the code that populates the data binding:

public static void Display(FrameworkElement parent, ImageData imageData)
{
    var purchaseWindow = new PurchaseWindow();

    var productQtyItems = new List<ProductQtyItem>();
    foreach (var p in SystemSettings.GetInstance().ProductList.Collection)
    {
        int qty = 0;
        imageData.ProductListItemQty.TryGetValue(p.Id, out qty);
        productQtyItems.Add(ProductQtyItem.Create(p, qty));
    }

    purchaseWindow.LayoutRoot.DataContext = new ProductListModel
    {
        ImageData = imageData,
        ProductQtyItems = productQtyItems
    };

    purchaseWindow.Show();
}

Here is the Model that is being set to the LayoutRoot.Datacontext:

public class ProductListModel : PropertyChangedBase
{
    private List<ProductQtyItem> _productQtyItems;
    private ImageData _imageData;

    public List<ProductQtyItem> ProductQtyItems
    {
        get { return _productQtyItems; }
        set { _productQtyItems = value; }
    }

    public ImageData ImageData
    {
        get { return _imageData; }
        set { _imageData = value; }
    }
}

And finally the ProductQtyItem:

public class ProductQtyItem : PropertyChangedBase
{
    public static ProductQtyItem Create(ProductItem productItem, int qty)
    {
        return new ProductQtyItem
        {
            _productItem = productItem,
            _qty = qty,
        };
    }

    private ProductItem _productItem;
    private int _qty;

    public int Id { get { return _productItem.Id; } }
    public int SortOrder { get { return _productItem.SortOrder; } }
    public string ItemName { get { return _productItem.ItemName; } }
    public string Description { get { return _productItem.Description; } }
    public double Price { get { return _productItem.Price; } }
    public bool IsQtyEnabled { get { return _productItem.IsQtyEnabled; } }

    public int Qty
    {
        get { return _qty; }
        set
        {
            if (value != _qty)
            {
                _qty = value;
                NotifyPropertyChanged("Qty");
            }
        }
    }

    public override bool Equals(object obj)
    {
        var other = obj as ProductQtyItem;

        if (other == null)
            return false;

        return Id == other.Id;
    }

    public override int GetHashCode()
    {
        return Id;
    }
}
هل كانت مفيدة؟

المحلول

The error message indicates that DataContext of controls that bound to properties ItemName, Price, Description is ProductListModel instead of ProductQtyItem.

Which model/viewmodel has property named Collection and of what type is Collection? I think the problem is here, if it is of type ProductListModel.

UPDATE :

Responding to your update, try to change resource definition from ControlTemplate :

<ControlTemplate x:Key="ProductItemTemplate" TargetType="ItemsControl">..</ControlTemplate>

to DataTemplate :

<DataTemplate x:Key="ProductItemTemplate">..</DataTemplate>

then bind ItemsControl's ItemTemplate property instead of Template property :

<ItemsControl 
            HorizontalAlignment="Left" Margin="0,105,0,0" VerticalAlignment="Top" Width="521" Height="377"          
            ItemTemplate="{StaticResource ProductItemTemplate}" 
            ItemsSource="{Binding ProductQtyItems}"/>

PS : actually there are too many information posted, and still not directly reproduceable, because some classes definition still missing. Next time try to simplify the scenario using reduced viewmodel, remove unrelated resources (styles, converters), but make sure the problem still appears.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top