ListView 内的 UserControl 数据绑定失败
UserControl databinding inside ListView fails
我有一个自定义控件,这里简化一下:
<UserControl x:Class="WPF.TestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPF"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
</Grid>
</UserControl>
使用情况:
<local:TestControl Grid.Row="0">
<Border BorderBrush="Red" BorderThickness="1">
<TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
</Border>
</local:TestControl>
目前一切顺利,有效。
但是,当用作 ListView 的 DataTemplate 的一部分时,绑定不再有效:
<ListView ItemsSource="{Binding Path=Items}" Grid.Row="2">
<ListView.Resources>
<DataTemplate DataType="{x:Type local:TestViewModel}">
<local:TestControl>
<TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
</local:TestControl>
</DataTemplate>
</ListView.Resources>
</ListView>
需要什么咒语才能使上面的数据绑定工作?
您正在创建一个无限循环。
UserControl
已经是一个 ContentControl
,因为它派生自它。所以只要你不覆盖它的ControlTemplate
,你就不应该向它添加一个ContentPresenter
,它在模板中使用时绑定到TemplatedParent
。
这种痛苦的导火索是 TemplatedParent
绑定。 TestControl
是模板的一部分。该模板应用于 ListViewItem
,因此它是 TestControl
的模板化父级。
现在TestControl
里面的ContentPresenter
的绑定源的值是ListViewItem.Content
属性的值,它持有TestControl
本身。通过这种方式,您可以将模板化父 ListViewItem.Content
添加到 TestControl
的 ContentPresenter
,后者现在包含相同的 TestControl
(本身),它将模板化父 ListViewItem.Content
(即 TestControl
)绑定到 TestControl
的 ContentPresenter
,后者现在包含相同的 TestControl
(自身),它绑定模板化的父... Whosebug。
如果你想像 ContentControl
一样使用 UserControl
即显示其他 "external" 控件的视觉效果,那么像 ContentCobtrol
一样使用它是:
测试控制
<UserControl x:Class="TestControl">
</UserControl>
数据模板
<DataTemplate DataType="{x:Type local:TestViewModel}">
<local:TestControl>
<TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
</local:TestControl>
</DataTemplate>
或者如果内容比简单的演示更复杂和高级,您应该覆盖 ControlTemplate
:
测试控制
<UserControl x:Class="TestControl">
<UserControl.Template>
<ControlTemplate TargetType="local:TreeIndex">
<Border>
<Grid>
...
<ContentPresenter Content="{TemplateBinding Content}" />
</Grid>
</Border>
</ControlTemplate>
</UserControl.Template>
</UserControl>
数据模板
<DataTemplate DataType="{x:Type local:TestViewModel}">
<local:TestControl>
<TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
</local:TestControl>
</DataTemplate>
我有一个自定义控件,这里简化一下:
<UserControl x:Class="WPF.TestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPF"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
</Grid>
</UserControl>
使用情况:
<local:TestControl Grid.Row="0">
<Border BorderBrush="Red" BorderThickness="1">
<TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
</Border>
</local:TestControl>
目前一切顺利,有效。
但是,当用作 ListView 的 DataTemplate 的一部分时,绑定不再有效:
<ListView ItemsSource="{Binding Path=Items}" Grid.Row="2">
<ListView.Resources>
<DataTemplate DataType="{x:Type local:TestViewModel}">
<local:TestControl>
<TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
</local:TestControl>
</DataTemplate>
</ListView.Resources>
</ListView>
需要什么咒语才能使上面的数据绑定工作?
您正在创建一个无限循环。
UserControl
已经是一个 ContentControl
,因为它派生自它。所以只要你不覆盖它的ControlTemplate
,你就不应该向它添加一个ContentPresenter
,它在模板中使用时绑定到TemplatedParent
。
这种痛苦的导火索是 TemplatedParent
绑定。 TestControl
是模板的一部分。该模板应用于 ListViewItem
,因此它是 TestControl
的模板化父级。
现在TestControl
里面的ContentPresenter
的绑定源的值是ListViewItem.Content
属性的值,它持有TestControl
本身。通过这种方式,您可以将模板化父 ListViewItem.Content
添加到 TestControl
的 ContentPresenter
,后者现在包含相同的 TestControl
(本身),它将模板化父 ListViewItem.Content
(即 TestControl
)绑定到 TestControl
的 ContentPresenter
,后者现在包含相同的 TestControl
(自身),它绑定模板化的父... Whosebug。
如果你想像 ContentControl
一样使用 UserControl
即显示其他 "external" 控件的视觉效果,那么像 ContentCobtrol
一样使用它是:
测试控制
<UserControl x:Class="TestControl">
</UserControl>
数据模板
<DataTemplate DataType="{x:Type local:TestViewModel}">
<local:TestControl>
<TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
</local:TestControl>
</DataTemplate>
或者如果内容比简单的演示更复杂和高级,您应该覆盖 ControlTemplate
:
测试控制
<UserControl x:Class="TestControl">
<UserControl.Template>
<ControlTemplate TargetType="local:TreeIndex">
<Border>
<Grid>
...
<ContentPresenter Content="{TemplateBinding Content}" />
</Grid>
</Border>
</ControlTemplate>
</UserControl.Template>
</UserControl>
数据模板
<DataTemplate DataType="{x:Type local:TestViewModel}">
<local:TestControl>
<TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
</local:TestControl>
</DataTemplate>