x:Bind 和用户控件

x:Bind and UserControls

我正在尝试在 UWP 中使用编译的 绑定 和一个简单的用例。

为了使我的 XAML 更易于管理,我将 DataTemplate 的 XAML 提取到 UserControl。所以我改造了这个

MainPage.xaml

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <ListView ItemsSource="{x:Bind ViewModel.Items}">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:ProjectItem">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{x:Bind Name, Mode=OneWay}" />
                    <TextBlock Text="{x:Bind Description, Mode=OneWay}" />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Page>

进入这个

MainPage.xaml

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <ListView ItemsSource="{x:Bind ViewModel.Items}">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:ProjectItem">
                <local:MyUserControl1 />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Page>

MyUserControl1.xaml

<UserControl
    x:Class="App1.MyUserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">

    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{x:Bind Name}" />
        <TextBlock Text="{x:Bind Description}" />
    </StackPanel>
</UserControl>

问题是它甚至无法编译,因为 x:Bind 不知道上下文。

x:Bind 如何涵盖此用例?

如果您使用这种方法,您可以(或者更确切地说需要)将 属性 添加到 MyUserControl1.xaml.cs,将当前的 DataContext 转换为 ProjectItem 和 returns它:

public ProjectItem Item => DataContext as ProjectItem;

public MyUserControl1()
{
    InitializeComponent();
    DataContextChanged += (s, e) => Bindings.Update();
}

然后在 XAML 标记中绑定到此 属性:

<StackPanel Orientation="Horizontal">
    <TextBlock Text="{x:Bind Item.Name}" />
    <TextBlock Text="{x:Bind Item.Description}" />
</StackPanel>

另一种选择是使用未编译的 {Bindings} 或摆脱 MyUserControl1 并恢复为内联 DataTemplate.

我建议在您的 MyUserControl1.xaml.cs

上为 ProjectItem 创建依赖关系 属性
  public static readonly DependencyProperty ProjectItemProperty =
        DependencyProperty.Register(
            nameof(ProjectItem),
            typeof(ProjectItem),
            typeof(MyUserControl1),
            null);

    public ProjectItem ProjectItem
    {
        get => (ProjectItem)GetValue(ProjectItemProperty);
        set => SetValue(ProjectItemProperty, value);
    }

然后在您的 XAML 上绑定您的 ProjectItem 依赖项的属性 属性:

<StackPanel Orientation="Horizontal">
    <TextBlock Text="{x:Bind ProjectItem.Name, Mode=OneWay}" />
    <TextBlock Text="{x:Bind ProjectItem.Description, Mode=OneWay}" />
</StackPanel>

然后在你的 MainPage.xaml 上传递 'ProjectItem' collection 项目。

<DataTemplate x:DataType="local:ProjectItem">
            <local:MyUserControl1 ProjectItem="{x:Bind}"/>
        </DataTemplate>

这可能会更快,因为 DataContext 仅在 ControlLoaded 时施放一次。

public ProjectItem ProjectItem { get; private set; }

public MyUserControl1()
{
    InitializeComponent();
    Loaded += (s, e) => 
    {
        ProjectItem = (ProjectItem)DataContext;
        Bindings.Update();
    };
}

如果 DataContextMainPage 中发生变化,请添加此内容:

    DataContextChanged += (s, e) => 
    {
        ProjectItem = (ProjectItem)DataContext;
        Bindings.Update();
    };

根据@mm8的回答。