【问题标题】:MVVM binding error?MVVM 绑定错误?
【发布时间】:2012-08-25 13:32:03
【问题描述】:

在下面的第一个块中,我故意遗漏了一个绑定语句,以便与第二个块进行比较。不同之处在于 在 'ag2.item...' 行上找不到属性。
item 是我的模型。

在块 2 中,您可以看到它指向我的视图模型 (ag2.viewModel.itemViewModel)。

我需要在我的 XAML 或我的代码隐藏中做什么才能让它指向我的类而不是视图模型?

区块 1:

BindingExpression 路径错误:“itemModel1”属性未在 'ag2.item,ag2,版本=1.0.0.0,文化=中性, PublicKeyToken=null'。 BindingExpression:路径='itemModel1' DataItem='ag2.item,ag2,版本=1.0.0.0, 文化=中立,PublicKeyToken=null';目标元素是 'Windows.UI.Xaml.Controls.TextBlock' (Name='null');目标属性是 “文本”(输入“字符串”)

第 2 块:

BindingExpression 路径错误:'itemModel' 属性未在 'ag2.viewModel.itemViewModel,ag2,版本=1.0.0.0,文化=中性, PublicKeyToken=null'。 BindingExpression:路径='itemModel' DataItem='ag2.viewModel.itemViewModel, ag2, 版本=1.0.0.0, 文化=中立,PublicKeyToken=null';目标元素是 'Windows.UI.Xaml.Controls.TextBlock' (Name='null');目标属性是 “源”(类型“字符串”)

代码块 2:

    itemViewModel VM = new itemViewModel((Int32)navigationParameter);
    DataContext = VM;

我还应该注意,在第 1 块中,我正在绑定到设置了 ItemSource="{Binding item}" 的 GridView。

在第 2 块中,我使用网格和文本块构建了我的 UI:Text="{Binding Path=itemModel}"

更新:试图获得更好的理解。我把我的代码放在那里:这是 XAML,下面是 ViewModel,下面是我的模型……我是 MVVM 的新手,所以我真的不知道我做错了什么。非常感谢任何帮助。

XAML:

<common:LayoutAwarePage
    x:Name="pageRoot"
    x:Class="autoGarage2.VehicleItemDetailPage"
    IsTabStop="false"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:common="using:autoGarage2.Common"
    xmlns:local="using:autoGarage2"
    xmlns:data="using:autoGarage2"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">


    <!--
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    -->
    <Grid Style="{StaticResource LayoutRootStyle}">

        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="2*"/>
        </Grid.RowDefinitions>

        <!-- Back button and page title -->
        <Grid
         Style="{StaticResource LayoutRootStyle}" Grid.Row="0">

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
            <TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Style="{StaticResource PageHeaderTextStyle}" Grid.Column="1"/>
        </Grid>



        <Grid Grid.Row="1">


            <Grid.ColumnDefinitions>
               <ColumnDefinition Width="Auto"/> 
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="3*"/>
                <RowDefinition Height="1*"/>
            </Grid.RowDefinitions>


                <StackPanel Grid.Row="0" Orientation="Horizontal" Width="auto" Margin="50,0,0,0" VerticalAlignment="Top"  >
                    <Grid HorizontalAlignment="Left" Width="250" Height="250">
                        <Border Background="White" BorderBrush="CornflowerBlue" BorderThickness="1">
                                <Image Source="{Binding Image}" Margin="50"/>
                            </Border>
                            <StackPanel VerticalAlignment="Bottom" Background="CornflowerBlue">
                                <StackPanel Orientation="Horizontal" DataContext="{Binding vehicles}">
                                <TextBlock Text="{Binding VehicleMake}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource PageSubheaderTextStyle}" Margin="5"/>
                                <TextBlock Text="{Binding VehicleModel}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource PageSubheaderTextStyle}" Margin="5"/>
                                </StackPanel>
                            </StackPanel>
                        </Grid>
                </StackPanel>
                    <StackPanel Grid.Row="0" Grid.Column="1">
                        <Grid Margin="20,0,0,20">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="1*"/>
                                <RowDefinition Height="1*"/>
                                <RowDefinition Height="1*"/>
                                <RowDefinition Height="1*"/>                                
                                <RowDefinition Height="1*"/>                                
                                <RowDefinition Height="1*"/>
                                <RowDefinition Height="1*"/>
                                <RowDefinition Height="1*"/>
                                <RowDefinition Height="1*"/>                                
                                <RowDefinition Height="1*"/>    
                                <RowDefinition Height="1*"/> 
                                <RowDefinition Height="1*"/> 
                                <RowDefinition/>                                
                            </Grid.RowDefinitions>

                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="2*"/>
                            </Grid.ColumnDefinitions>






                            <TextBlock Text="Vehicle Make:" Grid.Row="0" Grid.Column="0" FontSize="25" Foreground="Black" />
                            <TextBox Text="{Binding Path=VehicleMake}"  Grid.Row="0" Grid.Column="1" FontSize="25" BorderBrush="CornflowerBlue" BorderThickness="1"/>

                            <TextBlock Text="Vehicle Model:" FontSize="25" Foreground="Black" Grid.Row="1" Grid.Column="0"/>
                            <TextBox Text="{Binding VehicleModel}"  Grid.Row="1" Grid.Column="1" FontSize="25" BorderBrush="CornflowerBlue" BorderThickness="1"/>                            

                            <TextBlock Text="Vehicle Year:" FontSize="25" Foreground="Black" Grid.Row="2" Grid.Column="0"/>
                            <TextBox Text="{Binding VehicleYear}"  Grid.Row="2" Grid.Column="1" FontSize="25" BorderBrush="CornflowerBlue" BorderThickness="1"/>

                            <TextBlock Text="License Plate:" FontSize="25" Foreground="Black" Grid.Row="3" Grid.Column="0"/>
                            <TextBox Text=""  Grid.Row="3" Grid.Column="1" FontSize="25" BorderBrush="CornflowerBlue" BorderThickness="1"/> 

                            <TextBlock Text="VIN #" FontSize="25" Foreground="Black" Grid.Row="4" Grid.Column="0"/>
                            <TextBox Text=""  Grid.Row="4" Grid.Column="1" FontSize="25" BorderBrush="CornflowerBlue" BorderThickness="1" />    

                            <TextBlock Text=" Current Mi/Km" FontSize="25" Foreground="Black" Grid.Row="5" Grid.Column="0"/>
                            <TextBox Text=""  Grid.Row="5" Grid.Column="1" FontSize="25" BorderBrush="CornflowerBlue" BorderThickness="1"/>              

                            <TextBlock Text="" FontSize="25" Foreground="Black" Grid.Row="6" Grid.ColumnSpan="2"/>

                            <TextBlock Text="Last Oil Change" FontSize="25" Foreground="Black" Grid.Row="7" Grid.Column="0"/>
                            <TextBox Text=""  Grid.Row="7" Grid.Column="1" FontSize="25" BorderBrush="CornflowerBlue" BorderThickness="1"/>              

                            <TextBlock Text="Last Oil Change Mi/Km" FontSize="25" Foreground="Black" Grid.Row="8" Grid.Column="0"/>
                            <TextBox Text=""  Grid.Row="8" Grid.Column="1" FontSize="25" BorderBrush="CornflowerBlue" BorderThickness="1"/>

                            <TextBlock Text="" FontSize="25" Foreground="Black" Grid.Row="9" Grid.ColumnSpan="2"/>

                            <TextBlock Text="Reminder Mi/Km" FontSize="25" Foreground="Black" Grid.Row="10" Grid.Column="0"/>
                            <TextBox Text=""  Grid.Row="10" Grid.Column="1" FontSize="25" BorderBrush="CornflowerBlue" BorderThickness="1"/>     

                            <TextBlock Text="Reminder Month(s)" FontSize="25" Foreground="Black" Grid.Row="11" Grid.Column="0"/>
                            <TextBox Text=""  Grid.Row="11" Grid.Column="1" FontSize="25" BorderBrush="CornflowerBlue" BorderThickness="1"/>                          

                        </Grid>                     
                </StackPanel>

            </Grid>

    </Grid>
</common:LayoutAwarePage>

查看模型:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using Windows.Foundation.Collections;
using System.IO;


namespace autoGarage2.viewModel
{
    class vehicleViewModel
    {
        private IList<vehicle> m_vehicles;
        private IList<vehicle> m_vehicleItem;

        public IList<vehicle> vehicles
        {
            get { return m_vehicles; }
            set { m_vehicles = value; }
        }

        public IList<vehicle> vehicleItem
        {
            get { return m_vehicleItem; }
            set { m_vehicleItem = value; }
        }

        private IList<vehicle> getVehicleDetail(Int32 vId)
        {
            var vehicleItem =
                from v in vehicles
                where v.VehicleId == vId
                select v;
            if (vId > 0)
            {
                //vehicles.Clear();
                m_vehicles = new List<vehicle>();
                foreach (var item in vehicleItem)
                {
                    m_vehicles = new List<vehicle>
                    {
                        new vehicle(item.VehicleId, item.VehicleMake.ToString(), item.VehicleModel.ToString(), item.VehicleYear, item.Image.ToString())
                    };
                    //vehicle myVehicle = new vehicle(item.VehicleId, item.VehicleMake.ToString(), item.VehicleModel.ToString(), item.VehicleYear, item.Image.ToString());
                    //m_vehicles.Add(myVehicle);
                }

            }

            return m_vehicles;
        }

        public vehicleViewModel(Int32 vId)
        {
                m_vehicles = new List<vehicle>
                {        
                new vehicle(1, "Mazda", "3", 2011, "Assets/car2.png"),
                new vehicle(2, "Chevy", "Tahoe", 2004, "Assets/jeep1.png"),
                new vehicle(3, "Honda", "Goldwing", 2007 ,"Assets/moto1.png")
                };

                if (vId > 0)
                {
                    //m_vehicles = new List<vehicle>();
                    //m_vehicles = 
                    //getVehicleDetail(vId);
                    m_vehicles = new List<vehicle>
                    {        
                    new vehicle(2, "Chevy", "Tahoe", 2004, "Assets/jeep1.png"),
                    };

                }
        }



        #region dbCode

        //string dbName = "vehicle.db";


        //var dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, dbName);    
        //using (var db = new SQLite.SQLiteConnection(dbPath))    
        //    {
        //        var list = db.Table<vehicle>().ToList();
        //        m_vehicles = new List<vehicle>();
        //        for (Int32 i = 0; i < list.Count; i++)
        //        {
        //            //m_vehicles.Add(db.Table<vehicle>().ToList());
        //        }
        //    }




        //foreach (vehicle item in m_vehicles)
        //{
        //    AllItems.Add(item);
        //}      
        #endregion

    }
}

型号:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using SQLite;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;

namespace autoGarage2
{
    class vehicle : autoGarage2.Common.BindableBase
    {
        public vehicle()
        { 
        }

        public vehicle(string imagePath)
        {
            this._imagePath = imagePath;
        }
        public vehicle(Int32 vId, string vMake, string vModel, Int16 vYear, string imagePath)
        {
            this.m_vehicleID = vId;
            this.m_vehicleMake = vMake;
            this.m_vehicleModel = vModel;
            this.m_vehicleYear = vYear;
            this.m_vehicleName = vMake + " " + vModel;
            this._imagePath = imagePath;
        }


        private Int32 m_vehicleID;

        private String m_vehicleMake;
        private String m_vehicleModel;
        private Int16 m_vehicleYear;
        private string m_vehicleName;


        private ImageSource _image = null;
        private String _imagePath = null;
        private static Uri _baseUri = new Uri("ms-appx:///");

        //[AutoIncrement, PrimaryKey]
        public Int32 VehicleId
        {
            get
            {
                return m_vehicleID;
            }
            set
            {
                m_vehicleID = value;
                OnPropertyChanged("VehicleId");
            }
        }

        public String VehicleMake
        {
            get
            {
                return m_vehicleMake;
            }
            set
            {
                m_vehicleMake = value;
                OnPropertyChanged("VehicleMake");
            }
        }

        public String VehicleModel
        {
            get
            {
                return m_vehicleModel;
            }
            set
            {
                m_vehicleModel = value;
                OnPropertyChanged("VehicleModel");
            }
        }
    public Int16 VehicleYear
    {
        get
        {
            return m_vehicleYear;
        }
        set
        {
            m_vehicleYear = value;
            OnPropertyChanged("VehicleYear");
        }
    }

    public string VehicleName
    {
        get
        {
            return m_vehicleName;
        }
        set
        {
            m_vehicleName = value;
            OnPropertyChanged("VehicleName");
        }
    }

    public ImageSource Image
    {
        get
        {
            if (this._image == null && this._imagePath != null)
            {
                this._image = new BitmapImage(new Uri(vehicle._baseUri, this._imagePath));
            }
            return this._image;
        }

        set
        {
            this._imagePath = null;
            this.SetProperty(ref this._image, value);
        }
    }

    public void SetImage(String path)
    {
        this._image = null;
        this._imagePath = path;
        this.OnPropertyChanged("Image");
    }
}

}

【问题讨论】:

  • 有点不清楚你在做什么,你想达到什么。您的视图模型的结构是什么?您的 XAML 的结构是什么?您是否尝试绑定到 itemModel? itemModel 是在哪里定义的?
  • 请查看更新后的问题。我添加了所有内容。如果您能提供帮助,我们将不胜感激
  • 还请说明您遇到的问题。上面的问题似乎引用了 ItemModel 的绑定错误,但是您的 XAML 中没有与 ItemModel 的绑定。哪个TextBox 导致了错误,您希望它绑定到什么?视图的 DataContext 设置在哪里?

标签: xaml windows-runtime winrt-xaml


【解决方案1】:

听起来您正在尝试将您的 TextBlock 数据绑定到不同的对象,而不是 ViewModel(这是您的窗口/控件的 DataContext)。如果这是正确的,您需要将TextBlockDataContext 或父Grid 设置为您想要数据绑定到的对象。

DataContext 用于确定控件的 DataBind 的路径,它沿可视树继承。因此,如果您的 DataContext 设置为 MyViewModel,并且您使用 Text="{Binding Path=itemModel}",您的绑定路径将为 MyViewModel.itemModel

如果您不想在绑定路径中包含MyViewModel,则需要更改相关控件或包含控件的DataContext。对于 MVVM,这通常是通过将另一个对象公开为 ViewModel 的属性来完成的。因此,如果您的 MyViewModel 有一个属性 ItemModel:

public class ItemModel
{
    public string Property1 { get; }
    public string Property2 { get; }
}

public class MyViewModel
{
    public ItemModel ItemModel { get; private set; }
}

那么您的 XAML 可能如下所示(假设 MyViewModel 是父窗口/控件的 DataContext)。

<Grid Grid.Row="1" DataContext="{Binding ItemModel}">
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBlock Text="{Binding property1}"/>
    <TextBlock Text="{Binding Property2}" Grid.Row="1"/>
</Grid>

这两个文本框将绑定到 ItemModel 对象的 Property1 和 Property2。

【讨论】:

  • 请查看我更新的问题。希望我的代码能帮助识别我做错了什么。
【解决方案2】:

您似乎正在尝试绑定到一个列表,但您没有在 XAML 中使用任何 ItemsControl。您可能应该使用 ListView 之类的东西,将其 ItemsSource 绑定到您的车辆或 vehicleItem 列表,使用 ItemTemplate/DataTemplate 来定义集合中每个项目的外观,如果您的集合发生更改,则使用 ObservableCollection 或引发 INotifyPropertyChanged.PropertyChanged 通知,如果你换掉你的收藏等。否则我建议阅读一些关于绑定ItemsControls的东西或者一本关于XAML的普通书,比如Adam Nathan的WPF Unleashed。似乎您正在设置 m_vehicles 只是为了在下一条语句中将其替换为新的。另外 - 您正在将 StackPanel 的 DataContext 设置为您的列表,这是允许的,但它不起作用,因为 StackPanel 元素的 DataContext 仍然是整个列表而不是它的项目,这是您得到的使用 ItemsControl。

【讨论】:

  • 感谢您的回答。我真的让它工作了。我稍后会发布我所做的。
【解决方案3】:

在一个周末不看数据后,我能够让我的数据显示出来。基本上我注意到我收到一个绑定错误,指出它在我的 autoGarage2.vehicles 列表中找不到该属性。因此,对于咧嘴一笑,我以这样的方式开始绑定:

{Binding vehicles[0].vehicleModel}

下次我运行它时,数据就在那里。在考虑了更多之后,我决定创建一个车辆对象,而不是填充列表对象,我只填充单个车辆属性。现在我正在做这样的事情:

{Binding vehicleSingle.vehicleModel}

感谢大家的帮助。我想这只是 MVVM 在 XAML 中工作方式的一个细微差别......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    • 2017-12-25
    • 2010-11-10
    • 2021-11-08
    • 2017-03-28
    • 2012-05-26
    相关资源
    最近更新 更多