2016-04-14 49 views
0

不知道这是不是我对WPF或Catel的理解,但是我有一个树视图,其中包含3个不同节点类型的数据模板。 2个节点类型可以绑定到一个删除按钮。按钮命令的绑定绑定到父控件的视图模型(而不是节点本身),并且该按钮被点击的节点的命令参数被传递。我提供的数据模板之一的小片段(整件事是太大,在此输入):TreeView绑定节点上的按钮CanExecute问题

<Grid Margin="10" x:Name="CriteriaGrid"> 
    <TreeView ItemsSource="{Binding Criteria}" > 
    <DataTemplate DataType="{x:Type self:Leaf}"> 
     <Button Command="{Binding Source={x:Reference CriteriaGrid}, Path=DataContext.DeleteLeaf}" 
       CommandParameter="{Binding}">X</Button> 

    </DataTemplate> 
    </TreeView> 
</Grid> 

视图模型(又只是一个小摘录):

public class ManageCriteriaViewModel : ViewModelBase 
{ 
    public ManageCriteriaViewModel() 
    { 
     DeleteLeaf = new Command<Leaf>(OnDeleteLeaf, CanDeleteLeaf); 
    } 

    private bool CanDeleteLeaf(Leaf leafNode) 
    { 
     return (leafNode?.Parent as Group) != null; 
    } 

    private void OnDeleteLeaf(Leaf leafNode) 
    { 
     // Some code 
    } 

    public Command<Leaf> DeleteLeaf { get; private set; } 
} 

的问题是当最初构造Tree时,命令参数始终为空,并且如果参数为null,那么我的CanExecute测试将返回false。所以当我的树最初显示时,我的所有按钮都被禁用。

但是,如果我点击任何按钮,所有这些按钮都会被重新评估并被启用,因为现在正在传递命令参数。

我曾尝试加入:

protected override Task InitializeAsync() 
{ 
    CommandManager.InvalidateRequerySuggested(); 
    ViewModelCommandManager.InvalidateCommands(true); 
    return base.InitializeAsync(); 
} 

在试图重新评估的UI被加载后,但这似乎并没有工作的所有命令。我在这里错过了什么?

回答

0

尝试切换命令参数和命令对象的顺序。原因是CommandParameter不可绑定,并且不会引发任何更改通知。因此,该命令在“更新”后没有被重新评估(它仍然是初始绑定过程)。

如果不工作,这样的事情可能:

protected override async Task InitializeAsync() 
{ 
    await base.InitializeAsync(); 

    _dispatcherService.BeginInvoke(() => ViewModelCommandManager.InvalidateCommands(true);); 
} 
+0

感谢您的建议海尔特,我想这两个选项既不似乎工作。也许我需要更深入地调试源代码。也许有些事情正在发生,这可以解释为什么InvalidateCommand不像单击鼠标那样做同样的事情。 – Bitfiddler

+0

尝试使用对象作为参数,而不是那天晚上帮助您找到问题 –

+0

尝试使用对象,不幸的是,参数仅在第一次显示树时为空。 – Bitfiddler