我在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" ...
但我希望了解为什么它不像我设计的那样有用。