XAML GridView ItemTemplate 未绑定到控件

Posted

技术标签:

【中文标题】XAML GridView ItemTemplate 未绑定到控件【英文标题】:XAML GridView ItemTemplate not binding to control 【发布时间】:2017-11-27 11:38:51 【问题描述】:

我有一个 GridView,其中有一个包含自定义控件的 ItemTemplate:

<GridView
    ItemsSource="Binding Ubicaciones.Ubicaciones">
    <GridView.ItemTemplate>
        <DataTemplate>
            <ctr:HabitacionControl
                Width="70"
                Height="140"
                Ubicacion="Binding"/>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

这是我的自定义用户控件:

<UserControl
        x:Class="MySln.Mucama.Controls.HabitacionControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:MySln.Mucama.Controls"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="200"
        d:DesignWidth="97">
    <UserControl.DataContext>
        <local:HabitacionControlVM/>
    </UserControl.DataContext>
    <Grid>
        <RelativePanel>
            <Image x:Name="Puerta" Source="ms-appx:///Assets/Puerta.jpg"
                   Grid.RowSpan="5"/>
            <TextBlock Text="Binding Ubicacion.StrNombreMesa,FallbackValue=####"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Foreground="AliceBlue"
                       FontWeight="ExtraBold"
                           RelativePanel.AlignHorizontalCenterWithPanel="True"/>
        </RelativePanel>
    </Grid>
</UserControl>

及其背后的代码:

public sealed partial class HabitacionControl : UserControl

    public HabitacionControl()
    
        this.InitializeComponent();
    

    public MyClass Ubicacion
    
        get  return (MyClass)GetValue(UbicacionProperty); 
        set  SetValue(UbicacionProperty, value); 
    

    // Using a DependencyProperty as the backing store for Ubicacion.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty UbicacionProperty =
        DependencyProperty.Register("Ubicacion", typeof(MyClass), typeof(HabitacionControl), new PropertyMetadata(new PropertyChangedCallback(OnUbicacionChanged)));

    private static void OnUbicacionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    
       //...
    

现在我需要将每个 Ubicaciones.Ubicaciones 绑定到我的 Customcontrol 的 Ubicación 属性。

在运行时,我的 gridview 会生成我的所有项目,但永远不会绑定到它的 Ubicacion 属性。

输出窗口中没有任何警告。

我错过了什么?还是做错了?

【问题讨论】:

从不明确设置 UserControl 的 DataContext,不管他们在在线教程或博客文章中告诉你什么。 @Clemens 不同意关闭。这个问题的 UserControlViewModel 和伪 DataContext 将其区分开来。这也是一个很好的、清晰的例子,我可以为做同样事情的人参考。我会欺骗关闭DataContext = this; 问题到你的例子:) 将 UserControl 的 DataContext 设置为本地视图模型还是设置其本身并不重要。重要的事实是,这样做可以防止控件从其父控件继承 DataContext。因此,请参阅Binding to custom control inside DataTemplate for ItemsControl,了解如何在 UserControl 的 XAML 中编写 Bindngs。 【参考方案1】:

我的,看这里:

<UserControl.DataContext>
    <local:HabitacionControlVM/>
</UserControl.DataContext>

有人卖给你一张肮脏、肮脏的商品。可能是那些跑来跑去告诉人们DataContext = this;的混蛋是个好主意。

对不起,切线。现在看看这个:

<ctr:HabitacionControl 
    Width="70" 
    Height="140" 
    Ubicacion="Binding"/>

我看到了什么?这是一个伪 DataContext 属性吗?这是一个伪 DataContext 属性。问题是Binding 作用于HabitacionControl 的DataContext 中的对象不是它的父对象HabitacionControl 的 DataContext 是什么?

<UserControl.DataContext>
    <local:HabitacionControlVM/>
</UserControl.DataContext>

这就是为什么您不为您的用户控件创建视图模型的原因。您已经破坏了数据绑定的工作方式。视图模型必须通过 DataContext 沿可视树向下流动。当你打断这个流程时,你就会失败。

让我问你——TextBox 有 TextBoxViewModel 吗? 没有。它有一个 绑定到的Text 属性。你如何绑定它?您的视图模型流入TextBox.DataContext,从而允许您将视图模型的属性绑定到 TextBox 上公开的属性。

还有其他巧妙的方法可以解决这个问题,但最好的解决方案是一开始就不要让自己陷入这种情况。

您需要放弃 HabitacionControlVM 并在您的视图模型可以绑定的 UserControl 的表面上公开 DependencyProperties,提供您的 UserControl 运行所需的任何内容。将您的 UI 逻辑放在 HabitacionControl 的代码隐藏中。

不,这不会破坏 MVVM。 UI 逻辑在代码隐藏中很好。

如果您的 HabitacionControlVM 正在执行不应该在代码隐藏中的繁重工作,那么只需将其重构为您的代码隐藏调用的类。

人们认为 UserControlViewModel 反模式应该是这样做的。真的不是。祝你好运。

【讨论】:

只是一个问题,我的控件现在可以访问每个 Ubicacion,但我的 DP 永远不会触发它的 PropertyChangedCallback 委托。

以上是关于XAML GridView ItemTemplate 未绑定到控件的主要内容,如果未能解决你的问题,请参考以下文章

XAML GridView ItemTemplate 未绑定到控件

Windows Store App XAML:Gridview 不全屏显示图像

基于 XAML 绑定到区域性名称属性,使用不同区域性在 WPF GridView 中本地化货币值

在 UWP XAML 中自动调整网格列

如何在wpf应用程序中使gridview成为树视图的子元素

在 Gridview 内的 Gridview 上显示 Json