无法在WPF UserControl的DataGrid行中访问命令

时间:2015-07-08 11:22:23

标签: c# wpf xaml

我无法在用户控件中执行Command(TestCommand),可能是因为usercontrol的DataGrid使用FileDetailsList(List)

以下是wpf表单,我正在使用MVVM

<Window>
    <TabControl>
        <TabItem Header="Result">
            <USERCONTROL:FileSearchResult></USERCONTROL:FileSearchResult>
        </TabItem>
    </TabControl>
</Window>

以下是用户控件

<UserControl>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="30"></RowDefinition>
        </Grid.RowDefinitions
        <DataGrid Grid.Row="0" ItemSource="{Binding FileDetailsList}">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button>View
                                <Button.ContextMenu>
                                    <ContextMenu FontSize="11">
                                            <MenuItem Command="{Binding TestCommand}" CommandParameter="{Binding FileId}" Header="Splitter Errors"/>
                                    </ContextMenu>
                                </Button.ContextMenu>
                            </Button>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Binding="{Binding FileId}" Header="File ID"/>
                <DataGridTextColumn Binding="{Binding FileName}" Header="File Name"/>
            <DataGrid.Columns>
        <DataGrid Grid.Row="0">
    </Grid>
</UserControl>

以下是视图模型

public class FileDetailsViewModel : INotifyPropertyChanged
{
    private List<FileDetail> _fileDetailsList = new List<FileDetail>();

    public RelayCommand<Int32> TestCommand { get; private set; }
    public FileDetailsViewModel()
    {
         TestCommand = new RelayCommand<int>(OpenTestCommand);
    }

    private void OpenTestCommand(int fileId)
    {
         ///Some code
    }        

    public List<FileDetail> FileDetailsList { get { return _fileDetailsList; } set { _fileDetailsList = value; NotifyPropertyChanged("FileDetailsList"); } }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

请帮助解决此问题

3 个答案:

答案 0 :(得分:1)

你试试这个它将100%工作,

 <Button Tag="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}">
                                    View
                                    <!--  Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.  -->
                                    <Button.ContextMenu>
                                        <ContextMenu FontSize="11">
                                            <MenuItem Command="{Binding Path=PlacementTarget.Tag.TestCommand,
                                                                        RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"
                                                      CommandParameter="{Binding FileId}"
                                                      Header="Splitter Errors" />
                                        </ContextMenu>
                                    </Button.ContextMenu>
                                </Button>

答案 1 :(得分:0)

像这样使用menuitem命令绑定,

<MenuItem Command="{Binding DataContext.TestCommand, RelativeSource={RelativeSource AncestorType=DataGrid }}"

答案 2 :(得分:0)

WPF规则1:

当绑定不起作用时,请检查输出窗口!

你会看到错误说,FileDetails中不存在TestCommand。这是因为DataGrid中每一行的DataContext以及包括ContextMenu在内的所有后代元素都不是FileDetailsViewModel而是FileDetail

最简单的解决方法是将TestCommand移至FileDetail类。

另外,您可以修改绑定以指向FileDetailsViewModel。在UserControl或Window中为root元素命名,例如:LayoutRoot。然后在绑定中使用ElementName:

    <MenuItem Command="{Binding LayoutRoot.DataContext.TestCommand, ElementName=LayoutRoot}" 
              CommandParameter="{Binding FileId}" 
              Initialized="ContextMenu_Initialized"/>
    private void ContextMenu_Initialized(object sender, EventArgs e)
    {
        NameScope.SetNameScope((ContextMenu)sender, NameScope.GetNameScope(this));
    }

如何修复绑定的另一种方法是由@ jobyjames85提出的解决方法,但它有点笨拙。另一方面,它是简单的xaml解决方案,不涉及代码隐藏