绑定ListBox中Usercontrol的DependencyProperty

Posted

技术标签:

【中文标题】绑定ListBox中Usercontrol的DependencyProperty【英文标题】:Bind DependencyProperty of Usercontrol in ListBox 【发布时间】:2014-06-22 00:10:38 【问题描述】:

我需要 ListBox,其中列出了我的 UserControl。我的用户控件有文本框。所以我想在用户控件的文本框中显示列表子项的属性。我已经尝试了很多使用 DataContext 和 ElementName 的选项 - 它只是不起作用。我只是坚持下去。使其工作的唯一方法是将 UserControl 的 DataContext 绑定删除到自身并更改项目属性名称,使其与 DependencyProperty 名称匹配 - 但我需要在具有不同实体的不同视图模型中重用我的控件,因此几乎不可能使用接近。

有趣的是,如果我将我的 UserControl 更改为 Textbox 并绑定它的 Text 属性 - 一切正常。 Textbox 和我的 UserControl 有什么区别?

所以让我展示一下我的代码。 我已经简化了代码,只显示必要的:

控制 XAML:

<UserControl x:Class="TestControl.MyControl"
         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" 
         mc:Ignorable="d" 
         d:DesignHeight="100" d:DesignWidth="200"
         DataContext="Binding RelativeSource=RelativeSource Self">
    <Grid>
        <TextBlock Text="Binding Text"/>
    </Grid>
</UserControl>

控制 CS:

    public partial class MyControl : UserControl
    
        public MyControl()
        
            InitializeComponent();
         
        public string Text
        
            get  
                return (string)this.GetValue(TextProperty); 
            set  
                this.SetValue(TextProperty, value); 
        
        public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MyControl), new propertyMetadata(""));

窗口 XAML:

<Window x:Class="TestControl.MainWindow"
        Name="_windows"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestControl"
        Title="MainWindow" Height="350" Width="525" >
    <Grid Name="RootGrid">
        <ListBox ItemsSource="Binding ElementName=_windows, Path=MyList">
            <ItemsControl.ItemTemplate >
                <DataTemplate >
                    <local:MyControl Text="Binding Path=Name"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

窗口 CS:

public partial class MainWindow : Window
    
        public MainWindow()
        
            _list = new ObservableCollection<Item>();
            _list.Add(new Item("Sam"));
            _list.Add(new Item("App"));
            _list.Add(new Item("H**"));
            InitializeComponent();

        
        private ObservableCollection<Item> _list;

        public ObservableCollection<Item> MyList
        
            get  return _list;
            set 
        
    
    public class Item
    
        public Item(string name)
        
            _name = name;
        

        private string _name;

        public string Name
        
            get  return _name; 
            set  _name = value; 
        
    

【问题讨论】:

【参考方案1】:

这是 XAML 中的一个非常大的问题。问题是当您在用户控件中执行此操作时:

DataContext="Binding RelativeSource=RelativeSource Self"

你改变它的数据上下文,所以在这一行:

<local:MyControl Text="Binding Path=Name"/>

运行时现在将尝试在“MyControl”实例上解析“Name”,而不是在继承的数据上下文(即视图模型)上解析。 (通过检查输出窗口确认这一点——您应该会看到一个绑定错误。)

您可以通过使用RelativeSource 绑定来解决此问题,而不是这样设置用户控件的数据上下文:

<UserControl x:Class="TestControl.MyControl"
         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" 
         mc:Ignorable="d" 
         d:DesignHeight="100" d:DesignWidth="200"
    <Grid>
        <TextBlock 
            Text="Binding Text,RelativeSource=RelativeSource AncestorType=UserControl"
        />
    </Grid>
</UserControl>

【讨论】:

"这是 XAML 中的一个非常大的问题。" - 这太轻描淡写了,我花了好几个小时才终于找到答案

以上是关于绑定ListBox中Usercontrol的DependencyProperty的主要内容,如果未能解决你的问题,请参考以下文章

使用 MVVM 时,绑定不适用于 ListBox

WPF 从后面的代码添加的 UserControl 绑定到祖先

实现点击Form区域内除ListBox以外的其他地方,实现ListBox的隐藏,包括UserControl范围内,也包括UserControl之外Form之内

winform中如何设置提示框在winform窗体中居中显示?

如何为ListBox的每个项添加“删除”按钮并实现其功能?

ObservableCollection刷新视图MVVM