命令参数 Datagrid SelectedItems 为空
Command Parameter Datagrid SelectedItems is null
所以我找到了这个答案 Pass command parameter from the xaml,我认为它帮助我完成了大部分工作。我遇到的问题是当我 select 数据网格中的一行触发命令但 selected 项目为空时。
我不知道并且怀疑是问题所在,我应该在视图模型中将 selecteditems 传递给什么类型?目前我正在使用 IList,如我的视图模型代码所示:
namespace Project_Manager.ViewModel
{
public class ProjectSummaryViewModel : ObservableObject
{
public ProjectSummaryViewModel()
{
ProjectSummary = DatabaseFunctions.getProjectSummaryData();
}
private ObservableCollection<ProjectSummaryModel> projectsummary;
public ObservableCollection<ProjectSummaryModel> ProjectSummary
{
get { return projectsummary; }
set
{
projectsummary = value;
OnPropertyChanged("ProjectSummary");
}
}
public ICommand DeleteRowCommand
{
get { return new ParamDelegateCommand<IList<ProjectSummaryModel>>(DeleteRow); }
}
private void DeleteRow(IList<ProjectSummaryModel> projectsummaryselected)
{
string name = projectsummaryselected[0].ProjectName;
}
}
}
数据网格的 XAML 查看代码如下所示:
<Window x:Class="Project_Manager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<!--<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <!--Menu row-->
<RowDefinition Height="Auto"/> <!--button row-->
<RowDefinition/> <!--Current projects-->
<RowDefinition/> <!--Completed projects-->
</Grid.RowDefinitions>
<!--<Menu>
<MenuItem Header="File">
<MenuItem Header="New Project Management" CommandTarget="{Binding NewTable}"/>
<MenuItem Header="Open Project Management"/>
<Separator/>
<MenuItem Header="Exit"/>
</MenuItem>
<MenuItem Header="View">
<MenuItem x:Name="ViewCompleted" IsCheckable="True" IsChecked="True" Header="View Completed Projects List"/>
</MenuItem>
<MenuItem Header="Project Management">
<MenuItem Header="New Project"/>
</MenuItem>
</Menu>-->
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Button Content="Create New Project" Command="{Binding Path=NewProjectCommand}"/>
<!--<Button Content="View Details" Visibility="{Binding Source={x:Reference Name=CurrentProjectsDataGrid}, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"/>-->
</StackPanel>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Current Projects" Background="LemonChiffon"/>
<DataGrid x:Name="SummaryDataGrid" ItemsSource="{Binding ProjectSummary}" Grid.Row="1" AutoGenerateColumns="True" Style="{StaticResource DataGridStyle}">
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete Row" Command="{Binding DeleteRowCommand}" CommandParameter="{Binding SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"/>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
</Grid>
<!--<DataGrid.Columns>
<DataGridTextColumn Header="Project Name" Binding=""/>
<DataGridTextColumn Header="Team Name"/>
<DataGridTextColumn Header="Latest Update"/>
<DataGridTextColumn Header="Date Started"/>
</DataGrid.Columns>-->
<!--<Grid Grid.Row="3">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
--><!--<TextBlock Text="Completed Projects" Background="LightGreen" Visibility="{Binding Source={x:Reference Name=ViewCompleted}, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<DataGrid Grid.Row="1" AutoGenerateColumns="False" Style="{StaticResource DataGridStyle}" Visibility="{Binding Source={x:Reference Name=ViewCompleted}, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}">
<DataGrid.Columns>
<DataGridTextColumn Header="Project Name"/>
<DataGridTextColumn Header="Team"/>
<DataGridTextColumn Header="Date Completed"/>
</DataGrid.Columns>
</DataGrid>--><!--
</Grid>-->
</Grid>
为了以防万一这是一个命令实现问题,这里是我正在使用的自定义委托命令:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
namespace Project_Manager.Common
{
public class ParamDelegateCommand<T> : ICommand
{
public event EventHandler CanExecuteChanged;
private Action<T> executeMethod;
//private Func<T, bool> canExecuteMethod;
public ParamDelegateCommand(Action<T> executeMethod) //, Func<T, bool> canExecuteMethod)
{
this.executeMethod = executeMethod;
//this.canExecuteMethod = canExecuteMethod;
}
public bool CanExecute(object parameter)
{
return true; //canExecuteMethod((T)parameter);
}
public void Execute(object parameter)
{
executeMethod((T)parameter);
}
}
}
我四处搜索,可以找到很多 XAML 绑定的示例,但我似乎找不到它的另一半。那么视图模型中应该是什么类型呢?或者,实际问题是什么?
编辑:刚注意到调试 window 的一个错误,可能对某人有帮助
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DataGrid', AncestorLevel='1''. BindingExpression:Path=SelectedItems; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'CommandParameter' (type 'Object')
试试这个
<MenuItem Header="Delete Row" Command="{Binding DeleteRowCommand}" CommandParameter="{Binding SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"/>
如果您使用上下文菜单,请参考下面的代码来获取 SelectedItems。
<ContextMenu>
<MenuItem Header="Delete Row" Command="{Binding DeleteRowCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.SelectedItems}"/>
</ContextMenu>
Selecteditems 也是一个 IList,因此请按如下所示更改代码。
public ICommand DeleteRowCommand
{
get { return new ParamDelegateCommand<IList>(DeleteRow); }
}
private void DeleteRow(IList projectsummaryselected)
{
string name = (projectsummaryselected[0] as ProjectSummaryModel).ProjectName;
}
所以我找到了这个答案 Pass command parameter from the xaml,我认为它帮助我完成了大部分工作。我遇到的问题是当我 select 数据网格中的一行触发命令但 selected 项目为空时。
我不知道并且怀疑是问题所在,我应该在视图模型中将 selecteditems 传递给什么类型?目前我正在使用 IList,如我的视图模型代码所示:
namespace Project_Manager.ViewModel
{
public class ProjectSummaryViewModel : ObservableObject
{
public ProjectSummaryViewModel()
{
ProjectSummary = DatabaseFunctions.getProjectSummaryData();
}
private ObservableCollection<ProjectSummaryModel> projectsummary;
public ObservableCollection<ProjectSummaryModel> ProjectSummary
{
get { return projectsummary; }
set
{
projectsummary = value;
OnPropertyChanged("ProjectSummary");
}
}
public ICommand DeleteRowCommand
{
get { return new ParamDelegateCommand<IList<ProjectSummaryModel>>(DeleteRow); }
}
private void DeleteRow(IList<ProjectSummaryModel> projectsummaryselected)
{
string name = projectsummaryselected[0].ProjectName;
}
}
}
数据网格的 XAML 查看代码如下所示:
<Window x:Class="Project_Manager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<!--<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <!--Menu row-->
<RowDefinition Height="Auto"/> <!--button row-->
<RowDefinition/> <!--Current projects-->
<RowDefinition/> <!--Completed projects-->
</Grid.RowDefinitions>
<!--<Menu>
<MenuItem Header="File">
<MenuItem Header="New Project Management" CommandTarget="{Binding NewTable}"/>
<MenuItem Header="Open Project Management"/>
<Separator/>
<MenuItem Header="Exit"/>
</MenuItem>
<MenuItem Header="View">
<MenuItem x:Name="ViewCompleted" IsCheckable="True" IsChecked="True" Header="View Completed Projects List"/>
</MenuItem>
<MenuItem Header="Project Management">
<MenuItem Header="New Project"/>
</MenuItem>
</Menu>-->
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Button Content="Create New Project" Command="{Binding Path=NewProjectCommand}"/>
<!--<Button Content="View Details" Visibility="{Binding Source={x:Reference Name=CurrentProjectsDataGrid}, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"/>-->
</StackPanel>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Current Projects" Background="LemonChiffon"/>
<DataGrid x:Name="SummaryDataGrid" ItemsSource="{Binding ProjectSummary}" Grid.Row="1" AutoGenerateColumns="True" Style="{StaticResource DataGridStyle}">
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete Row" Command="{Binding DeleteRowCommand}" CommandParameter="{Binding SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"/>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
</Grid>
<!--<DataGrid.Columns>
<DataGridTextColumn Header="Project Name" Binding=""/>
<DataGridTextColumn Header="Team Name"/>
<DataGridTextColumn Header="Latest Update"/>
<DataGridTextColumn Header="Date Started"/>
</DataGrid.Columns>-->
<!--<Grid Grid.Row="3">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
--><!--<TextBlock Text="Completed Projects" Background="LightGreen" Visibility="{Binding Source={x:Reference Name=ViewCompleted}, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<DataGrid Grid.Row="1" AutoGenerateColumns="False" Style="{StaticResource DataGridStyle}" Visibility="{Binding Source={x:Reference Name=ViewCompleted}, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}">
<DataGrid.Columns>
<DataGridTextColumn Header="Project Name"/>
<DataGridTextColumn Header="Team"/>
<DataGridTextColumn Header="Date Completed"/>
</DataGrid.Columns>
</DataGrid>--><!--
</Grid>-->
</Grid>
为了以防万一这是一个命令实现问题,这里是我正在使用的自定义委托命令:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
namespace Project_Manager.Common
{
public class ParamDelegateCommand<T> : ICommand
{
public event EventHandler CanExecuteChanged;
private Action<T> executeMethod;
//private Func<T, bool> canExecuteMethod;
public ParamDelegateCommand(Action<T> executeMethod) //, Func<T, bool> canExecuteMethod)
{
this.executeMethod = executeMethod;
//this.canExecuteMethod = canExecuteMethod;
}
public bool CanExecute(object parameter)
{
return true; //canExecuteMethod((T)parameter);
}
public void Execute(object parameter)
{
executeMethod((T)parameter);
}
}
}
我四处搜索,可以找到很多 XAML 绑定的示例,但我似乎找不到它的另一半。那么视图模型中应该是什么类型呢?或者,实际问题是什么?
编辑:刚注意到调试 window 的一个错误,可能对某人有帮助
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DataGrid', AncestorLevel='1''. BindingExpression:Path=SelectedItems; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'CommandParameter' (type 'Object')
试试这个
<MenuItem Header="Delete Row" Command="{Binding DeleteRowCommand}" CommandParameter="{Binding SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"/>
如果您使用上下文菜单,请参考下面的代码来获取 SelectedItems。
<ContextMenu>
<MenuItem Header="Delete Row" Command="{Binding DeleteRowCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.SelectedItems}"/>
</ContextMenu>
Selecteditems 也是一个 IList,因此请按如下所示更改代码。
public ICommand DeleteRowCommand
{
get { return new ParamDelegateCommand<IList>(DeleteRow); }
}
private void DeleteRow(IList projectsummaryselected)
{
string name = (projectsummaryselected[0] as ProjectSummaryModel).ProjectName;
}