【问题标题】:Property can't be found on ViewModel in UWP app在 UWP 应用中的 ViewModel 上找不到属性
【发布时间】:2017-12-02 00:07:45
【问题描述】:

UWP 中的订单表单使用模板 10 将产品添加到订单中。错误是

Invalid binding path 'OrderViewModel.FindProduct_TextChanged' : Property 'OrderViewModel' can't be found on type 'ProductViewModel'

相关的xaml sn-p是

<Page.DataContext>
    <ViewModels:MainPageViewModel x:Name="OrderViewModel" />
</Page.DataContext>

<GridView  ItemsSource="{x:Bind OrderViewModel.Products, Mode=TwoWay}">
    <GridView.ItemTemplate>
        <DataTemplate x:DataType="ViewModels:ProductViewModel" >
            <AutoSuggestBox 
                Name="ProductAutoSuggestBox" 
                TextMemberPath="{x:Bind ItemCode, Mode=TwoWay}"
                TextChanged="{x:Bind OrderViewModel.FindProduct_TextChanged}">
            </AutoSuggestBox>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

OrderViewModel 和 ProductViewModel 中的相关 sn-p

namespace ViewModels
{    
    public class OrderViewModel : ViewModelBase
    {
        public ObservableCollection<Product> Products { get; set; } = new ObservableCollection<Product>();

        public void FindProduct_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
        { ... }
    }

    public class ProductViewModel : ViewModelBase
    {
        string _ItemCode = default(string);
        public string ItemCode { get { return _ItemCode; } set { Set(ref _ItemCode, value); } }

        public ProductViewModel()
        {
        }
    }
}

如何从引用 ProductViewModel 的 GridView 的 DataTemplate 中正确引用 OrderViewModel 上的 FindProduct_TextChanged

【问题讨论】:

  • 你使用OrderViewModel.Products作为ItemsSource,这意味着x:DataType必须是Product并且FindProduct_TextChanged方法必须放在里面。
  • 谢谢@tao。我不太清楚你的意思。 Product 不是 OrderViewModel 的成员,但 ProductsOrderViewModel 的成员。 FindProduct_TextChanged 更新了OrderViewModel.Products,所以我看不出除了OrderViewModel 之外的任何地方。还是我误会了?您能否提供一个代码 sn-p 来说明您的意思?

标签: xaml uwp uwp-xaml template10


【解决方案1】:

投票赞成@tao 的评论。 @Vague,我想您可能误解了 x:DataType 的用途。可以参考Data binding in depth的“DataTemplate and x:DataType”部分:

在数据模板中使用 {x:Bind} 时,可以在编译时验证其绑定(并为它们生成有效的代码),DataTemplate 需要使用 x:DataType 声明其数据对象的类型.

对于您的场景,从您的代码public ObservableCollection&lt;Product&gt; Products { get; set; } = new ObservableCollection&lt;Product&gt;();,您的DataTemplate 的数据对象的类型应该是您的Product 类,而不是您的ProductViewModel,同时,您的FindProduct_TextChanged 事件必须可以在这个Product 类中找到,这意味着你的FindProduct_TextChanged 代码应该放在你的Product 数据模型中。

顺便说一句,我认为ItemsSource 没有必要使用TwoWay 绑定。对于这种情况,绑定目标是GridViewItemsSource,绑定源是ObservableCollection&lt;Product&gt; Products,我知道您想在更新集合时更新GridView,这是使用ObservableCollection 完成的工作。另外,这里只能更改绑定源来通知绑定目标,所以OneWay绑定就足够了。不过你的代码问题不大。

所以对于你的GridView,它应该是这样的:

<GridView  ItemsSource="{x:Bind OrderViewModel.Products, Mode=OneWay}">
    <GridView.ItemTemplate>
        <DataTemplate x:DataType="Models:Product" >
            <AutoSuggestBox 
                Name="ProductAutoSuggestBox" 
                TextMemberPath="{x:Bind ItemCode, Mode=TwoWay}"
                TextChanged="{x:Bind FindProduct_TextChanged}">
            </AutoSuggestBox>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

【讨论】:

  • 谢谢@Grace Feng - MSFT。你是说FindProduct_TextChanged 应该在Products 类上吗?如果是这样,也许我应该有ObservableCollection&lt;ProductViewModel&gt; Products { get; set; } = new ObservableCollection&lt;ProductViewModel&gt;(); 然后x:DataType="Models:ProductViewModel" 并把FindProduct_TextChanged 放在ProductViewModel 上。这听起来像是更好的方法吗? `
  • @Vague,是的,如果您坚持使用ProductViewModel 作为您的数据模型,那么您是对的。但通常我们这里需要使用数据模型,而不是视图模型。
  • 谢谢@Grace Feng - MSFT。我不认为使用功能FindProduct_TextChanged 污染模型是一种好习惯,因为这是特定于视图的。还是我误会了?
  • @Vahue,通常是的,但重要的是您的FindProduct_TextChanged 用于DataTemplate 内部的控件,当控件放置在DataTemplate 中时,它们实际上成为每个项目的模型,不是真正的控件,这就是为什么我们不能使用它们的名称直接访问它们的原因。如果允许,我们通常使用Command 处理数据模型中的事件。有很多关于这个的讨论,你可以谷歌他们。
【解决方案2】:

如果错误有点像这样,我批准了它的字符集支持错误: 错误无效的绑定路径“XX.YY”:在类型“CCC”上找不到属性“ZZ”

xaml 和 C# 都支持 unicode; 这是因为您在类属性中使用了非 ascii 字符。这是我今天发现的一个错误。只需将您的类属性字符重命名为 ascii 标准。希望能解决。

【讨论】:

    猜你喜欢
    • 2019-05-31
    • 1970-01-01
    • 2021-12-17
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    • 2020-11-08
    相关资源
    最近更新 更多