WPF自定义控件:DependencyProperty TwoWay绑定

|| 我有这个自定义UserControl,它具有一个列表和一个按钮:
<UserControl x:Class=\"WpfApplication1.CustomList\"
         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=\"300\" d:DesignWidth=\"300\">
    <Grid>
        <ListBox Name=\"listBox1\" ItemsSource=\"{Binding ListSource}\" HorizontalAlignment=\"Right\" Width=\"174\" />
        <Button Name=\"ButtonAdd\" Content=\"Add\" HorizontalAlignment=\"Left\" Width=\"101\" />
    </Grid>
</UserControl>
后面的代码具有IEnumerable类型的DependencyProperty和Button的处理程序(OnAdd):
public partial class CustomList : UserControl
{
    public CustomList( )
    {
        InitializeComponent( );
    ButtonAdd.Click += new RoutedEventHandler( OnAdd );
    }

private void OnAdd( object sender, EventArgs e )
{
    IList<object> tmpList = this.ListSource.ToList( );
    Article tmpArticle = new Article( );
    tmpArticle .Name = \"g\";
    tmpList.Add(tmpArticle );
    ListSource = (IEnumerable<object>) tmpList;
}

    public IEnumerable<object> ListSource
    {
        get
        {
            return (IEnumerable<object>)GetValue( ListSourceProperty );
        }
        set
        {
            base.SetValue(CustomList.ListSourceProperty, value);
        }
    }

    public static DependencyProperty ListSourceProperty = DependencyProperty.Register(
         \"ListSource\",
         typeof( IEnumerable<object> ),
         typeof( CustomList ),
         new PropertyMetadata( OnValueChanged ) );

    private static void OnValueChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
    {
        ( (CustomList)d ).ListSource = (IEnumerable<object>)e.NewValue;
    }
}
在按钮处理程序中,我试图将一个Article添加到ListSource(绑定到Articles)。 这是我使用UserControl(CustomList)的窗口:
<Window x:Class=\"WpfApplication1.MainWindow\"
        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"
        xmlns:local=\"clr-namespace:WpfApplication1\"
        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"
        DataContext=\"{Binding RelativeSource={RelativeSource Self}}\"
        Title=\"MainWindow\" Height=\"350\" Width=\"525\">
    <Grid>
        <local:CustomList ListSource=\"{Binding Articles, Mode=TwoWay}\" Margin=\"80,0,0,0\" />
    </Grid>
</Window>
当我单击按钮时,Articles变为null,而不是在Articles集合中添加Article。并且ListSource属性也变为null。我在这里做错什么了吗?这是预期的行为吗?如果是,执行此操作的另一种方式是: 创建一个将具有一个列表和一个按钮的自定义控件,该按钮的处理程序将在列表中添加对象。     
已邀请:
这里有很多问题,但是导致您出现问题的主要原因是,您试图在其上使用TwoWay绑定的属性之间可能存在类型不匹配。您没有列出Articles属性的代码,但我认为它可能像ListSource属性那样是
IEnumerable<Article>
ObservableCollection<Article>
,而不是
IEnumerable<object>
。 当您设置双向绑定并且目标值无法转换回源类型(即
IEnumerable<object>
->
ObservableCollection<Article>
)时,source属性(此处为条款)将收到一个空值,然后将其推回绑定到目标属性(此处为ListSource)。 您可以在任一侧更改类型,但是如果您将它们与“双向绑定”一起使用,则类型应该匹配。 通常,将TwoWay绑定与集合一起使用是一个坏主意。无需每次都想进行更改就复制和替换集合实例,只需在一个实例中添加和删除项目即可。由于该实例在(OneWay)绑定的两侧都是相同的集合,因此更新将同时在两侧显示,并且如果您使用的是ObservableCollection,则还可以在任一侧获取更改通知。 您还应该摆脱OnValueChanged代码,因为它只是将属性重置为刚刚在属性上设置的值。     

要回复问题请先登录注册