UWP x:bind 问题 - 绑定路径无效 'dpl':属性 'dpl' 未在类型 'DataTemplate' 上找到
UWP x:bind issue - Invalid binding path 'dpl' : Property 'dpl' not found on type 'DataTemplate'
我有一个 class PricingData
和 PricingSchedule
。其中 PricingSchedule
是 PricingData
class 中的列表<>。我想将此 class 的数据绑定到 UWP 控件。
示例代码可在此处下载:https://github.com/jigneshdesai/SampleOfBindingIssue1.git
代码的外观: 我有一个托管 ListView 控件的起始页(主页),Listview 中有 PricingUserControl。 PricingUserControl 看起来像这样
<TextBlock x:Name="lblPriceHeader" Text="{Binding PricingTitle}" Margin="0,0,50,0" />
<ComboBox x:Name="cbPriceValueList" ItemsSource="{x:Bind dpl}" DisplayMemberPath="PriceValue" SelectedValuePath="PriceValue" SelectedValue="{Binding DisplayPricing}" />
<ListView x:Name="lbPriceChangeSchedule" ItemsSource="{Binding PricingScheduleList}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Horizontal">
<ComboBox x:Name="cbSchedulePriceValueList" ItemsSource="{x:Bind dpl}" DisplayMemberPath="PriceValue" SelectedValuePath="PriceValue" />
<TextBlock Text="{Binding SchedulePricingTimeZone }" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
我想要实现的目标:组合框应填充一个值列表(例如 1 美元、2 美元、3 美元等)。然后,当您提供数据库中的记录列表时,列表框将重复 PricingUserControl,其中的组合框应根据记录设置其值 属性 (SelectedValue)。
问题:
ComboBox x:Name="cbPriceValueList" 使用 x:bind dpl 其中 dpl 是 PricingUserControl 的局部变量。它会正确填充列表。问题是 ComboBox x:Name="cbSchedulePriceValueList" 它也有 x:bind dpl 但在编译期间它显示错误 "Invalid binding path 'dpl' : Property 'dpl' not found on type 'DataTemplate'."
我想知道为什么 x:bind dpl 此时不起作用。 ?
我现在意识到你的问题实际上是你需要从 DataTemplate
中到达 Page
属性,所以这里是更新的答案。
如果您需要从 DataTemplate
中访问外部元素的 属性,则不能使用 x:Bind
。相反,您可以使用经典的 {Binding}
表达式。首先为您的页面添加名称:
<Page
...
x:Name="Page">
现在从 DataTemplate
:
中引用这个名字
<ComboBox
x:Name="cbSchedulePriceValueList"
ItemsSource="{Binding ElementName=Page, Path=dpl}"
DisplayMemberPath="PriceValue"
SelectedValuePath="PriceValue" />
原回答
为了能够在 DataTemplate
中使用 x:Bind
,您必须使用 x:DataType
指定控件的各个项目将具有的数据类型。假设你的 PricingScheduleList
是一个 List<MyApp.Models.MyType>
,那么你首先需要将这个 XML 命名空间添加到 <Page>
元素:
xmlns:models="using:MyApp.Models"
然后设置x:DataType
属性如下:
<DataTemplate x:DataType="models:MyType">
...
</DataTemplate>
当您开始编写 x:Bind
表达式时,IntelliSense 现在应该向您建议 MyType
的属性,您可以确认这是否有效。
查看你的代码,SelectedValue不生效的原因是你在ComboBox中选择项目时,没有通知你的DisplayPricing改变。因此,您需要在 PricingData 中实现 INotifyPropertyChanged 接口。在 PricingSchedule 中执行相同的操作。
public class PricingData : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
......
public string DisplayPricing
{
get => $"{PricingValue} {PricingCurrency}";
set
{
var sp = value.Split(' ');
PricingValue = sp.First();
PricingCurrency = sp.Last();
OnPropertyChanged();
}
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
PScheduleUserControl.xaml:
<ComboBox x:Name="cbPriceValueList" ItemsSource="{x:Bind myList}" DisplayMemberPath="PriceValue" SelectedValuePath="PriceValue" SelectedValue="{Binding DisplayPricing,Mode=TwoWay}" />
我有一个 class PricingData
和 PricingSchedule
。其中 PricingSchedule
是 PricingData
class 中的列表<>。我想将此 class 的数据绑定到 UWP 控件。
示例代码可在此处下载:https://github.com/jigneshdesai/SampleOfBindingIssue1.git
代码的外观: 我有一个托管 ListView 控件的起始页(主页),Listview 中有 PricingUserControl。 PricingUserControl 看起来像这样
<TextBlock x:Name="lblPriceHeader" Text="{Binding PricingTitle}" Margin="0,0,50,0" />
<ComboBox x:Name="cbPriceValueList" ItemsSource="{x:Bind dpl}" DisplayMemberPath="PriceValue" SelectedValuePath="PriceValue" SelectedValue="{Binding DisplayPricing}" />
<ListView x:Name="lbPriceChangeSchedule" ItemsSource="{Binding PricingScheduleList}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Horizontal">
<ComboBox x:Name="cbSchedulePriceValueList" ItemsSource="{x:Bind dpl}" DisplayMemberPath="PriceValue" SelectedValuePath="PriceValue" />
<TextBlock Text="{Binding SchedulePricingTimeZone }" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
我想要实现的目标:组合框应填充一个值列表(例如 1 美元、2 美元、3 美元等)。然后,当您提供数据库中的记录列表时,列表框将重复 PricingUserControl,其中的组合框应根据记录设置其值 属性 (SelectedValue)。
问题: ComboBox x:Name="cbPriceValueList" 使用 x:bind dpl 其中 dpl 是 PricingUserControl 的局部变量。它会正确填充列表。问题是 ComboBox x:Name="cbSchedulePriceValueList" 它也有 x:bind dpl 但在编译期间它显示错误 "Invalid binding path 'dpl' : Property 'dpl' not found on type 'DataTemplate'."
我想知道为什么 x:bind dpl 此时不起作用。 ?
我现在意识到你的问题实际上是你需要从 DataTemplate
中到达 Page
属性,所以这里是更新的答案。
如果您需要从 DataTemplate
中访问外部元素的 属性,则不能使用 x:Bind
。相反,您可以使用经典的 {Binding}
表达式。首先为您的页面添加名称:
<Page
...
x:Name="Page">
现在从 DataTemplate
:
<ComboBox
x:Name="cbSchedulePriceValueList"
ItemsSource="{Binding ElementName=Page, Path=dpl}"
DisplayMemberPath="PriceValue"
SelectedValuePath="PriceValue" />
原回答
为了能够在 DataTemplate
中使用 x:Bind
,您必须使用 x:DataType
指定控件的各个项目将具有的数据类型。假设你的 PricingScheduleList
是一个 List<MyApp.Models.MyType>
,那么你首先需要将这个 XML 命名空间添加到 <Page>
元素:
xmlns:models="using:MyApp.Models"
然后设置x:DataType
属性如下:
<DataTemplate x:DataType="models:MyType">
...
</DataTemplate>
当您开始编写 x:Bind
表达式时,IntelliSense 现在应该向您建议 MyType
的属性,您可以确认这是否有效。
查看你的代码,SelectedValue不生效的原因是你在ComboBox中选择项目时,没有通知你的DisplayPricing改变。因此,您需要在 PricingData 中实现 INotifyPropertyChanged 接口。在 PricingSchedule 中执行相同的操作。
public class PricingData : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
......
public string DisplayPricing
{
get => $"{PricingValue} {PricingCurrency}";
set
{
var sp = value.Split(' ');
PricingValue = sp.First();
PricingCurrency = sp.Last();
OnPropertyChanged();
}
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
PScheduleUserControl.xaml:
<ComboBox x:Name="cbPriceValueList" ItemsSource="{x:Bind myList}" DisplayMemberPath="PriceValue" SelectedValuePath="PriceValue" SelectedValue="{Binding DisplayPricing,Mode=TwoWay}" />