简体   繁体   English

在数据网格中添加上下文菜单,如何获取选择项值

[英]Add context menu in datagrid, how to get the select Item value

I am new in WPF programming with MVVM pattern.我是使用 MVVM 模式进行 WPF 编程的新手。 Now I have added the context menu in the datagrid.现在我在数据网格中添加了上下文菜单。 But, when I click the right mouse button, I don't know how to get the select row value.但是,当我单击鼠标右键时,我不知道如何获取选择行值。 this is my xmal这是我的 xmal

 <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>

And here is my viewModel这是我的 viewModel

 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]

Thank you very much非常感谢你

Expanding on Bolu's comment you could use SelectedItem to get the current item.扩展Bolu 的评论,您可以使用SelectedItem来获取当前项目。 Below is a quick example:下面是一个快速示例:

<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 is now bound to SelectedItemProperty in the ViewModel. SelectedItem现在绑定到 ViewModel 中的SelectedItemProperty

This is a common problem in WPF.这是 WPF 中的常见问题。 The solution is to utilise a Tag property in the item DataTemplate to hold the data item.解决方案是利用项DataTemplateTag属性来保存数据项。 First, let's add this part:首先,让我们添加这部分:

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

Now that we have access to the DataContext of the UserControl which can be found in the Tag property of each data object, let's bind to this from the ContextMenu ... we do it using a handy property called PlacementTarget :现在我们可以访问UserControlDataContext ,它可以在每个数据对象的Tag属性中找到,让我们从ContextMenu绑定到它……我们使用一个名为PlacementTarget的方便属性来完成它:

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

One thing to note is the YourCollection.CurrentItem property shown in the CommandParameter above.需要注意的一件事是上面CommandParameter显示的YourCollection.CurrentItem属性。 The CurrentItem property is a property that I added into my collection classes to bind to the SelectedItem properties of collection controls in the UI. CurrentItem属性是我添加到我的集合类中以绑定到 UI 中集合控件的SelectedItem属性的属性。 If you don't have one of these, it's ok, but you will need a property that is bound to the SelectedItem property of your collection control for this to work.如果你没有这些中的一个,它的确定,但你需要绑定到一个属性SelectedItem您的收藏控制的该物业的工作。 For my example, I have this:对于我的例子,我有这个:

<ListBox ItemsSource="{Binding YourCollection}" SelectedItem="{Binding 
YourCollection.CurrentItem}" />

bigworld12 has close to the right answer here, but it breaks if your context menu is templated. bigworld12 在这里的答案接近正确,但如果您的上下文菜单是模板化的,它就会中断。 Try:尝试:

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

for the code-behind.对于代码隐藏。 I used nullable operators in case you somehow get here without the expected parent tree and target (maybe by triggering the context menu while off the grid.)我使用了可为空的运算符,以防您以某种方式到达这里而没有预期的父树和目标(可能通过在离开网格时触发上下文菜单。)

I know this is an old question, but i wanted to share this very easy solution.我知道这是一个老问题,但我想分享这个非常简单的解决方案。

XAML: 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>

Code behind:后面的代码:

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

I think this is a similar case.我认为这是一个类似的案例。 I fixed it that way:我是这样修复的:

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

C# Code: C# 代码:

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

   DataGrid.ItemsSource contains ObservableCollection<MyTypeInRow>. 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM