4

我是使用 MVVM 模式进行 WPF 编程的新手。现在我在数据网格中添加了上下文菜单。但是,当我单击鼠标右键时,我不知道如何获取选择行值。这是我的圣诞节

 <DataGrid  AutoGenerateColumns="False" Grid.Row="1" CanUserAddRows="False" CanUserDeleteRows="False"
              ItemsSource="{Binding StoryList}">
        <DataGrid.Columns>
        <DataGridTextColumn Header="ID" Binding="{Binding ID}" Width="40" IsReadOnly="True" />
        <DataGridTextColumn Header="Title" Binding="{Binding Title}" Width="60" IsReadOnly="True"/>
        <DataGridTextColumn Header="StoryPoints" Binding="{Binding StoryPoints}" Width="90" IsReadOnly="True">
                <DataGridTextColumn.CellStyle>
                    <Style TargetType="DataGridCell">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding StoryPoints}" Value="0">
                                <Setter Property="Background" Value="Red"/>
                                <Setter Property="ToolTip" Value="Story Point cannot be 0."/>
                            </DataTrigger>                                
                        </Style.Triggers>
                    </Style>
                </DataGridTextColumn.CellStyle>
            </DataGridTextColumn>
            <DataGridTextColumn Header="Stack Rank" Binding="{Binding StackRank}" Width="80"/>
            <DataGridTextColumn Header="Estimate" Binding="{Binding Estimate}" Width="60"/>
            <DataGridTextColumn Header="CompletedWork" Binding="{Binding CompletedWork}" Width="120" />
            <DataGridTextColumn Header="RemainWork" Binding="{Binding RemainWork}" Width="110" />
            <DataGridTextColumn Header="CompleteProcess" Binding="{Binding CompletedProcess}" Width="110" />
            <DataGridTextColumn Header="YesterdayComments" Binding="{Binding YesterdayComments}" Width="120" />
            <DataGridTextColumn Header="TodayComments" Binding="{Binding TodayComments}" Width="120" />
        </DataGrid.Columns>
        <DataGrid.ContextMenu>
            <ContextMenu Name="StoryMenu" StaysOpen="True">
                <MenuItem Header="Add an Issue" Command="{Binding AddIssueCommand}" />
                <MenuItem Header="Burn Down Chart" Command="{Binding BurnDownChartCommand}"/>
            </ContextMenu>
        </DataGrid.ContextMenu>
    </DataGrid>

这是我的视图模型

 class MainViewModel:NotificationObject
{
    private ObservableCollection<Story> storyList;

    public ObservableCollection<Story> StoryList
    {
        get { return storyList; }
        set
        {
            storyList = value;
            this.RaisePropertyChanged("StoryList");
        }
    }
    public DelegateCommand AddIssueCommand { get; set; }
    public DelegateCommand BurnDownChartCommand { get; set; }
    private Story selectStory;

    public Story SelectStory
    {
        get { return selectStory; }
        set
        {
            selectStory = value;
            this.RaisePropertyChanged("SelectStory");
        }
    }

    public void LoadStory()
    {
        this.storyList = new ObservableCollection<Story>();
        Story story1 = new Story(){ID=1, Title="win App", StoryPoints=0, StackRank=1, Estimate=40, CompletedWork=10, RemainWork=30, CompletedProcess=25, TodayComments="Coding", YesterdayComments="N/a"};
        Story story2 = new Story() { ID = 2, Title = "win App", StoryPoints = 10, Estimate = 40, CompletedWork = 10, RemainWork = 30, CompletedProcess = 25, TodayComments = "Coding 20%", YesterdayComments = "N/a" };
        Story story3 = new Story() { ID = 3, Title = "win App", StoryPoints = 10, Estimate = 50, CompletedWork = 20, RemainWork = 30, CompletedProcess = 20, TodayComments = "Coding  30%", YesterdayComments = "N/a" };
        Story story4 = new Story() { ID = 4, Title = "win App", StoryPoints = 10, Estimate = 60, CompletedWork = 30, RemainWork = 30, CompletedProcess = 50, TodayComments = "Coding  40%", YesterdayComments = "N/a" };
        Story story5 = new Story() { ID = 5, Title = "win App", StoryPoints = 10, Estimate = 40, CompletedWork = 10, RemainWork = 30, CompletedProcess = 25, TodayComments = "Coding  50%", YesterdayComments = "N/a" };
        Story story6 = new Story() { ID = 6, Title = "win App", StoryPoints = 10, Estimate = 30, CompletedWork = 30, RemainWork = 0, CompletedProcess = 100, TodayComments = "Coding  60%", YesterdayComments = "N/a" };

        storyList.Add(story1);
        storyList.Add(story3);
        storyList.Add(story2);
        storyList.Add(story4);
        storyList.Add(story5);
        storyList.Add(story6);
    }
    public MainViewModel()
    {
        this.SelectStory = new Story();
        this.LoadStory();
        this.AddIssueCommand = new DelegateCommand(new Action(this.AddIssueCommandExecute));
    }

    public void AddIssueCommandExecute()
    {

        if (SelectStory != null)
        {
            System.Windows.MessageBox.Show("Add an Issue" + SelectStory.Title + "!");
        }
        else
        {
            System.Windows.MessageBox.Show("choose an story first!");
        }
        //System.Windows.MessageBox.Show("record" + RecordIndex);
    }
}![What I need][1]

非常感谢

4

5 回答 5

9

扩展Bolu 的评论,您可以使用它SelectedItem来获取当前项目。下面是一个简单的例子:

<DataGrid ItemsSource="{Binding Source}" SelectedItem="{Binding SelectedItemProperty, Mode=TwoWay}">
    <DataGrid.ContextMenu>
        <ContextMenu>
            <MenuItem Command="{Binding MyCommand}" Header="MyCommand"/>
        </ContextMenu>
    </DataGrid.ContextMenu>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Key, Mode=TwoWay}" Width="1*"/>
        <DataGridTextColumn Header="Value" Binding="{Binding Value, Mode=TwoWay}" Width="3*"/>
    </DataGrid.Columns>
</DataGrid>

SelectedItem现在绑定SelectedItemProperty在 ViewModel 中。

于 2016-05-23T10:25:06.207 回答
6

这是 WPF 中的常见问题。解决方案是利用项目中的Tag属性DataTemplate来保存数据项。首先,让我们添加这部分:

<DataTemplate DataType="{x:Type YourDataTypeXmlNamespace:YourDataType}">
    <Border Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={
x:Type YourViewsXmlNamespace:YourViewWhereThisIsDeclared}}}">
        ...
    </Border>
</DataTemplate>

现在我们可以访问可以在每个数据对象的DataContext属性中找到的 ,让我们从 ... 绑定到 this ,我们使用一个方便的属性来做到这一点:UserControlTagContextMenuPlacementTarget

<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={
RelativeSource Self}}">
    <MenuItem Header="Do Something" Command="{Binding YourCommandInYourViewModel}" 
CommandParameter="{Binding YourCollection.CurrentItem}">
        ...
    </MenuItem>
</ContextMenu>

需要注意的一件事是上面YourCollection.CurrentItem显示的属性CommandParameter。该CurrentItem属性是我添加到我的集合类中以绑定到SelectedItemUI 中集合控件的属性的属性。如果您没有其中之一,那没关系,但您需要一个绑定到SelectedItem您的集合控件属性的属性才能使其工作。对于我的例子,我有这个:

<ListBox ItemsSource="{Binding YourCollection}" SelectedItem="{Binding 
YourCollection.CurrentItem}" />
于 2013-09-04T10:28:40.413 回答
1

bigworld12 在这里有接近正确的答案,但如果您的上下文菜单是模板化的,它就会中断。尝试:

DataGridRow row =
            ((sender as MenuItem)?.GetAncestors()
               ?.FirstOrDefault(dpo => dpo.GetType() == typeof(ContextMenu)) as ContextMenu)
               ?.PlacementTarget as DataGridRow;

对于代码隐藏。我使用了可为空的运算符,以防您以某种方式到达这里而没有预期的父树和目标(可能是通过在离开网格时触发上下文菜单。)

于 2018-06-14T15:58:49.933 回答
0

我知道这是一个老问题,但我想分享这个非常简单的解决方案。

XAML:

<ContextMenu x:Key="MyRowMenu1" DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
     <MenuItem Click="MenuItem_Click" Header="Add to Favourites"/>
     <MenuItem Header="Copy" >
     <MenuItem Header="Copy Name"/>
     <MenuItem Header="Copy ID" />
     <MenuItem Header="Copy IP Adddress"/>
    </MenuItem>
</ContextMenu>

后面的代码:

Private Sub MenuItem_Click(sender As Object, e As RoutedEventArgs)
    Dim row As DataGridRow = DirectCast(DirectCast(DirectCast(sender, MenuItem).GetParentObject, ContextMenu).PlacementTarget, DataGridRow)
    'replace with what ever item you want
    Dim srvr As Server = DirectCast(row.Item, Server)

End Sub
于 2015-03-09T18:20:09.073 回答
0

我认为这是一个类似的案例。我是这样解决的:

<ContextMenu x:Key="rowContextMenu" Background="Transparent" >
<MenuItem Header="{StaticResource LowPriority}" Style="{StaticResource menuStyle}"  
CommandParameter="1" Click="ChangePriority"/>
</ContextMenu>

C#代码:

    private async void ChangePriority(object sender, RoutedEventArgs a)
    {
        MyTypeInRow row = (MyTypeInRow)(((MenuItem)sender).DataContext);
     ...
    }

   DataGrid.ItemsSource contains ObservableCollection<MyTypeInRow>. 
于 2020-10-11T17:41:52.760 回答