WPF自定义拖拽控件数据绑定失效问题求助
WPF自定义拖拽控件数据绑定失效问题排查
问题现象
创建支持拖拽的WPF自定义控件DraggableText,窗口中ListBox的ItemsSource绑定ViewModel的RevitLinks列表正常,但控件无法显示每个实例的Name属性。
相关代码片段
窗口使用控件的XAML
<Border Grid.Column="0" Margin="15" Background="#f8f9fa" CornerRadius="10" BorderBrush="#ced4da" BorderThickness="1"> <ListBox AllowDrop="True" Drop="HandleDrop" Background="Transparent" ItemsSource="{Binding RevitLinks, UpdateSourceTrigger=PropertyChanged}"> <ListBox.ItemTemplate> <DataTemplate> <local:DraggableText Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Border>
自定义控件XAML
<UserControl x:Class="myNameSpace.DraggableText" 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:myNameSpace" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" Height="20" Width="300" Background="Transparent"> <Grid> <TextBlock Text="{Binding Text}" Foreground="Black" /> </Grid> </UserControl>
自定义控件后台代码
partial class DraggableText : UserControl { public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof(string), typeof(DraggableText), new PropertyMetadata(defaultValue: "default")); public DraggableText() { InitializeComponent(); } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (e.LeftButton == MouseButtonState.Pressed) { DragDrop.DoDragDrop(this, this, DragDropEffects.Move); } } }
绑定失效原因
自定义控件内部的TextBlock使用{Binding Text}时,默认会继承当前的DataContext。而DraggableText作为ListBoxItem的内容,它的DataContext是RevitLinks列表中的单个实例对象(该对象只有Name属性,没有Text属性),因此绑定找不到对应的值,导致内容无法显示。
修复方案
有两种可靠的修复方式:
方式一:ElementName绑定
给UserControl设置名称,在TextBlock绑定中指定ElementName指向自身:
<UserControl x:Class="myNameSpace.DraggableText" ... x:Name="Self"> <Grid> <TextBlock Text="{Binding Text, ElementName=Self}" Foreground="Black" /> </Grid> </UserControl>
方式二:RelativeSource绑定
通过RelativeSource定位到父级UserControl,绑定其Text依赖属性:
<UserControl x:Class="myNameSpace.DraggableText" ...> <Grid> <TextBlock Text="{Binding Text, RelativeSource={RelativeSource AncestorType=UserControl}}" Foreground="Black" /> </Grid> </UserControl>
注意:不要直接设置
UserControl的DataContext = this,这会破坏控件继承外部DataContext的能力,后续绑定外部数据会出现异常。
内容的提问来源于stack exchange,提问作者bamec
相关产品推荐
相关产品推荐

