将ListBox ItemsSource绑定到CustomControl属性

时间:2012-05-09 02:32:49

标签: c# wpf binding itemssource

我在XAML中实现绑定时遇到了麻烦。 我编写了一个自定义控件,它公开了一个名为Path的类型为ShellContainer的依赖属性(实际上是一个IEnumerable,在Microsoft.WindowsAPICodePack.Shell命名空间中定义)。

我的控件实现了INotifyPropertyChanged,并且当(通过用户交互)其Path属性发生更改时,它会引发PropertyChangedEvent和/或自定义PathChangedEvent。 这两个事件似乎传播正确,实际上如果在我的主窗口的代码隐藏中我听一个或每两个事件,我随后改变我的ListBox ItemsSource,一切顺利。 如果在XAML中相反,我在ListBox ItemsSource和我的自定义控件的Path属性之间设置了一个绑定,当我与自定义控件交互时没有任何反应。

这是我的自定义控件

    public delegate void PathChangedEventHandler(object sender, PathChangedEventArgs e);

public class PathChangedEventArgs : EventArgs
{
    private ShellContainer oldValue, newValue;

    public PathChangedEventArgs(ShellContainer oldValue, ShellContainer newValue)
    {
        this.oldValue = oldValue;
        this.newValue = newValue;
    }

    public ShellContainer OldPath
    {
        get { return oldValue; }
    }

    public ShellContainer NewPath
    {
        get { return newValue; }
    }
}

public class PathBox : TextBox, INotifyPropertyChanged
{
    public static readonly DependencyProperty PathProperty;

    public event PropertyChangedEventHandler PropertyChanged;
    public event PathChangedEventHandler PathChanged;

    public ShellContainer Path
    {
        get { return GetValue(PathProperty) as ShellContainer; }
        set 
        {
            if (value is ShellContainer)
            {
                OnPathChanged(new PathChangedEventArgs(Path, value));
                SetValue(PathProperty, value);
            }
        }
    }

    static PathBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(PathBox), new FrameworkPropertyMetadata(typeof(PathBox)));
        PathProperty = DependencyProperty.Register("Path", typeof(ShellContainer), typeof(PathBox));
    }

    protected override void OnInitialized(EventArgs e)
    {
        TextChanged += new TextChangedEventHandler(UpdatePath);
        base.OnInitialized(e);
    }

    protected virtual void OnPathChanged(PathChangedEventArgs e)
    {
        OnPropertyChanged("Path");
        PathChanged(this, e);
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(name));
    }

    private void UpdatePath(object sender, TextChangedEventArgs e)
    {
        try
        {
            ShellObject shObj = ShellObject.FromParsingName(Text);
            if (shObj is ShellContainer) Path = shObj as ShellContainer;
        }
        catch { }
    }
}

这里是MainWindow XAML

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="32" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <ListBox Name="explorer" ItemsSource="{Binding ElementName=pathBox, Path=Path}" Grid.Row="1" />
    <local:PathBox Height="24" HorizontalAlignment="Left" Margin="4" VerticalAlignment="Top" Width="120"  x:Name="pathBox"/>
</Grid>

错误在哪里?当然,我可以使用一种解决方法,只需添加到MainWindow代码隐藏这几行

    public void pathBox_PathChanged(object sender, PathChangedEventArgs e)
    {
        explorer.ItemsSource = pathBox.Path;
    }

并使用

修改XAML
    <local:PathBox PathChanged="pathBox_PathChanged" ...

但我希望了解为什么它不像我设计的那样有用。

0 个答案:

没有答案