x:绑定和用户控件

Posted

技术标签:

【中文标题】x:绑定和用户控件【英文标题】:x:Bind and UserControls 【发布时间】:2020-02-09 00:47:15 【问题描述】:

我正在尝试通过一个简单的用例在 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 如何覆盖这个用例?

【问题讨论】:

使用x:Bind 绑定到框架元素(代码隐藏类),它需要在编译时固定所有类型。在这种情况下为什么还要使用x:Bind @Çöđěxěŕ:为什么?例如编译时安全。 @mm8 好点,因为用户已经看到... 【参考方案1】:

我建议在 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”集合项。

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

【讨论】:

如果ProjectItem 有 10 个属性怎么办?那么你需要创建 10 个依赖属性。因此,我们可以尝试创建一个依赖属性为ProjectItem?只是一个建议。【参考方案2】:

如果您使用这种方法,您可以(或者说需要)向MyUserControl1.xaml.cs 添加一个属性,将当前的DataContext 转换为ProjectItem 并返回它:

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

【讨论】:

以上是关于x:绑定和用户控件的主要内容,如果未能解决你的问题,请参考以下文章

WPF 用户控件中的数据绑定

当我以编程方式更改用户控件时,如何让数据绑定双向工作?

WPF - 绑定到用户控件之间的列表框的选定项

自定义用户控件的 DependencyProperty 绑定未在更改时更新

WebForms嵌套用户控件数据绑定

将自定义可序列化对象绑定到控件,以便用户和加载/保存首选项