为什么在展开 TreeViewItem 时调用命令不起作用?
Why invoking command when `TreeViewItem` is expanded doesn't work?
我试图在 TreeViewItem
按照 here 的解释展开时调用命令,但由于某种原因它不起作用。我认为是因为 HierarchicalDataTemplate
,但我不知道为什么。
有人知道问题出在哪里吗?
XAML
<Window x:Class="MyProject.MainWindow"
...
xmlns:local="clr-namespace:MyProject"
xmlns:bindTreeViewExpand="clr-namespace:MyProject"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TreeView ItemsSource="{Binding RootFolders}">
<TreeView.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="bindTreeViewExpand:Behaviours.ExpandingBehaviour" Value="{Binding ExpandingCommand}"/>
</Style>
</TreeView.Resources>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}" DataType="{x:Type local:DriveFolder}">
<TreeViewItem Header="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
</Window>
行为
namespace GooglePhotoPermissions
{
public static class Behaviours
{
#region ExpandingBehaviour (Attached DependencyProperty)
public static readonly DependencyProperty ExpandingBehaviourProperty =
DependencyProperty.RegisterAttached("ExpandingBehaviour", typeof(ICommand), typeof(Behaviours),
new PropertyMetadata(OnExpandingBehaviourChanged));
public static void SetExpandingBehaviour(DependencyObject o, ICommand value)
{
o.SetValue(ExpandingBehaviourProperty, value);
}
public static ICommand GetExpandingBehaviour(DependencyObject o)
{
return (ICommand)o.GetValue(ExpandingBehaviourProperty);
}
private static void OnExpandingBehaviourChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TreeViewItem tvi = d as TreeViewItem;
if (tvi != null)
{
ICommand ic = e.NewValue as ICommand;
if (ic != null)
{
tvi.Expanded += (s, a) =>
{
if (ic.CanExecute(a))
{
ic.Execute(a);
}
a.Handled = true;
};
}
}
}
#endregion
}
}
ViewModel
namespace MyProject
{
public class DriveFile
{
public string Name { get; set; }
public string Id { get; set; }
public bool IsFolder { get; protected set; }
public DriveFile()
{
IsFolder = false;
}
}
public class DriveFolder : DriveFile
{
public List<DriveFile> Children { get; set; }
public DriveFolder()
{
IsFolder = true;
Children = new List<DriveFile>();
}
}
public class DriveViewModel
{
public IList<DriveFolder> RootFolders
{
get
{
return GetRootFolders();
}
}
private ICommand _expandingCommand;
public ICommand ExpandingCommand
{
get
{
if (_expandingCommand == null)
{
_expandingCommand = new RelayCommand(Foo);
}
return _expandingCommand;
}
}
private DriveService _driveService;
private IList<DriveFolder> GetRootFolders()
{
...
}
}
}
一个
您的绑定有误。
您以适用于每个 TreeViewItem
的样式定义绑定。在此绑定中,源是每个 TreeViewItem
本身的 DataContext
。那将是 DriveFolder
或 DriveFile
对象。
当然,这些对象没有ExpandingCommand
属性,所以你的绑定就失败了。
更改您的绑定,将 TreeView
的 DataContext
用作源(以访问您的视图模型及其命令)。您可以使用 ElementName
或 RelativeSource
,例如像这样:
<Setter Property="bindTreeViewExpand:Behaviours.ExpandingBehaviour"
Value="{Binding DataContext.ExpandingCommand, RelativeSource={RelativeSource AncestorType=TreeView}}"/>
我试图在 TreeViewItem
按照 here 的解释展开时调用命令,但由于某种原因它不起作用。我认为是因为 HierarchicalDataTemplate
,但我不知道为什么。
有人知道问题出在哪里吗?
XAML
<Window x:Class="MyProject.MainWindow"
...
xmlns:local="clr-namespace:MyProject"
xmlns:bindTreeViewExpand="clr-namespace:MyProject"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TreeView ItemsSource="{Binding RootFolders}">
<TreeView.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="bindTreeViewExpand:Behaviours.ExpandingBehaviour" Value="{Binding ExpandingCommand}"/>
</Style>
</TreeView.Resources>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}" DataType="{x:Type local:DriveFolder}">
<TreeViewItem Header="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
</Window>
行为
namespace GooglePhotoPermissions
{
public static class Behaviours
{
#region ExpandingBehaviour (Attached DependencyProperty)
public static readonly DependencyProperty ExpandingBehaviourProperty =
DependencyProperty.RegisterAttached("ExpandingBehaviour", typeof(ICommand), typeof(Behaviours),
new PropertyMetadata(OnExpandingBehaviourChanged));
public static void SetExpandingBehaviour(DependencyObject o, ICommand value)
{
o.SetValue(ExpandingBehaviourProperty, value);
}
public static ICommand GetExpandingBehaviour(DependencyObject o)
{
return (ICommand)o.GetValue(ExpandingBehaviourProperty);
}
private static void OnExpandingBehaviourChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TreeViewItem tvi = d as TreeViewItem;
if (tvi != null)
{
ICommand ic = e.NewValue as ICommand;
if (ic != null)
{
tvi.Expanded += (s, a) =>
{
if (ic.CanExecute(a))
{
ic.Execute(a);
}
a.Handled = true;
};
}
}
}
#endregion
}
}
ViewModel
namespace MyProject
{
public class DriveFile
{
public string Name { get; set; }
public string Id { get; set; }
public bool IsFolder { get; protected set; }
public DriveFile()
{
IsFolder = false;
}
}
public class DriveFolder : DriveFile
{
public List<DriveFile> Children { get; set; }
public DriveFolder()
{
IsFolder = true;
Children = new List<DriveFile>();
}
}
public class DriveViewModel
{
public IList<DriveFolder> RootFolders
{
get
{
return GetRootFolders();
}
}
private ICommand _expandingCommand;
public ICommand ExpandingCommand
{
get
{
if (_expandingCommand == null)
{
_expandingCommand = new RelayCommand(Foo);
}
return _expandingCommand;
}
}
private DriveService _driveService;
private IList<DriveFolder> GetRootFolders()
{
...
}
}
}
一个
您的绑定有误。
您以适用于每个 TreeViewItem
的样式定义绑定。在此绑定中,源是每个 TreeViewItem
本身的 DataContext
。那将是 DriveFolder
或 DriveFile
对象。
当然,这些对象没有ExpandingCommand
属性,所以你的绑定就失败了。
更改您的绑定,将 TreeView
的 DataContext
用作源(以访问您的视图模型及其命令)。您可以使用 ElementName
或 RelativeSource
,例如像这样:
<Setter Property="bindTreeViewExpand:Behaviours.ExpandingBehaviour"
Value="{Binding DataContext.ExpandingCommand, RelativeSource={RelativeSource AncestorType=TreeView}}"/>