在通用Windows平台API中,如何使用x:绑定用户控件(旨在作为GridView的ItemTemplate的布局)绑定到GridView的ItemSource的实例属性?
背景
我正在尝试重新创建Windows 10股票应用程序中的布局,如体育,新闻,金钱等。
我正在使用两个GridViews作为应用程序的主要区域;一个用于“特色文章”(2张带有标题的大照片)和一张用于所有其他文章(带有标题的较小照片)。
我能够绑定到我在后面的代码中提供的数据源(一个List,其中NewsItem是一个带有Image和Headline属性的POCO)以下是MainPage.xaml的相关部分:
<Page ...
xmlns:data="using:NewsApp.Models" />
....
<GridView Name="FeaturedItems" Grid.Row="0">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:NewsItem">
<Grid Name="mainPanel" HorizontalAlignment="Stretch" Width="500" >
<Image Source="{x:Bind Image}" HorizontalAlignment="Stretch" />
<TextBlock Text="{x:Bind Headline}" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
....
图像和标题绑定得很好(即使它们没有正确设置样式)。但是,相反我认为我需要绑定到用户控件以获取我想要的样式选项,控制调整大小esp。当使用视觉状态触发器并简化XAML时(至少,这是我建议的技术。)
所以,我在项目中添加了一个新的用户控件(FeaturedItemControl.xaml),并复制到DataTemplate的子网格中:
<UserControl ... >
<Grid Name="mainPanel" HorizontalAlignment="Stretch" Width="500" >
<Image Source="{x:Bind Image}" HorizontalAlignment="Stretch" />
<TextBlock Text="{x:Bind Headline}" />
</Grid>
</UserControl>
然后回到MainPage.xaml,我更改DataTemplate以引用新的FeaturedItemControl:
<GridView Name="FeaturedItems" Grid.Row="0">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:NewsItem">
<local:FeaturedItemControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
但是,我收到了Image和Headline属性的错误消息:无效的绑定路径'Headline':在'FeaturedItemControl'类型上找不到属性'Headline'。
我已经尝试了一些事情,但是只是在没有理解我在做什么的情况下抛出代码来解决问题。任何帮助将不胜感激。
感谢您的关注。
答案 0 :(得分:8)
Using Depechie's answer, I formulated this little cheat cheat for posterity:
Do note that you MUST use this technique to utilize the VisualStateManager with items inside your data bound controls' (GridView, ListView) data templates.
1) Create a User Control.
2) Cut the content of the DataTemplate in your page and paste it into the User Control replacing the template's Grid.
3) Reference the User Control from inside the Data Template:
4) Modify the contents of the User Control changing x:Bind statements to utilize object.property notation:
<UserControl>
<StackPanel>
<Image Source="{x:Bind NewsItem.LeadPhoto}" />
<TextBlock Text="{x:Bind NewsItem.Headline}" />
<TextBlock Text="{x:Bind NewsItem.Subhead}" />
</StackPanel>
</UserControl>
5) Add this in the User Control's Code Behind:
public Models.NewsItem NewsItem { get { return this.DataContext as Models.NewsItem; } }
public ContactTemplate()
{
this.InitializeComponent();
this.DataContextChanged += (s, e) => Bindings.Update();
}
答案 1 :(得分:4)
可以在用户控件中使用x:Bind,但是您需要添加一些额外的代码。 我在项目中遇到了同样的问题,你可以在这里看到结果:https://github.com/AppCreativity/Kliva/tree/master/src/Kliva/Controls
所以你需要做的是,在你的用户控件后面的代码中创建一个指向正确的DataContext的属性。
如果这样做,您可以在控件的xaml中使用该DataContext的属性:例如:
请注意,在控件的构造函数中,您需要添加:DataContextChanged += (sender, args) => this.Bindings.Update();
,因为datacontext将根据您使用控件的页面而改变!
然后在放置此控件的页面上,您还需要执行相同操作以启用x:bind。
您可以在MainPage.DeviceFamily-Mobile.xaml
和MainPage.xaml.cs
文件的示例中看到这一点。
希望这有帮助。
答案 2 :(得分:3)
x:Bind并不像Binding / DataContext那样真正分层。另外,当您不直接在DataTemplate内部(例如在用户控件内)时,x:Bind尝试使用的对象是“this”而不是“this.DataContext”。我目前关于如何解决这类问题的思路是尝试不在任何地方使用UserControls。而是更喜欢ResourceDictionary中包含的DataTemplates。这种方法有一些非常强烈的警告,例如,如果你使用x:Bind在从ResourceDictionary项模板创建的数据模板中绑定(添加新项),你将会崩溃xaml编译器。你可以在这里找到一个非常完整的例子https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlBind在示例中要注意的重要事项是,它们显示正在使用的ResourceDictionary,它实际上只是一个ResourceDictionary.xaml,它也是一个ResourceDictionary.xaml.cs(这是生成的地方)来自x的代码:绑定结束)
另一种选择是在用户控件和x上添加标题和图像作为属性:将它们从模板中绑定,然后在用户控件中绑定x:正如您当前所做的那样绑定,但现在x:绑定生成的路径'this .Headline'将存在。不幸的是,命令事实上是绑定意味着你在用户控件中的x:Bind必须是OneWay而不是默认的OneTime。这是因为x:Bind OneTime在InitializeComponent调用中执行绑定,并且任何一组属性/ DataContext内容在完成之后才会完成。
总而言之,您有两个选择,在任何地方使用数据模板,或绑定到直接在用户控件上的属性。