我是使用MVVM模式进行WPF编程的新手。现在我在datagrid中添加了上下文菜单。但是,当我单击鼠标右键时,我不知道如何获取选择的行值。 这是我的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>
这是我的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]
非常感谢
答案 0 :(得分:6)
这是WPF中的常见问题。解决方案是利用项Tag
中的DataTemplate
属性来保存数据项。首先,让我们添加这部分:
<DataTemplate DataType="{x:Type YourDataTypeXmlNamespace:YourDataType}">
<Border Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={
x:Type YourViewsXmlNamespace:YourViewWhereThisIsDeclared}}}">
...
</Border>
</DataTemplate>
现在我们可以访问DataContext
的{{1}} UserControl
,可以在每个数据对象的Tag
属性中找到它,让我们从ContextMenu
绑定到PlacementTarget
...我们使用名为<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
属性。 SelectedItem
属性是我添加到我的集合类中的属性,用于绑定到UI中集合控件的SelectedItem
属性。如果你没有其中一个,那没关系,但你将需要一个绑定到你的集合控件的<ListBox ItemsSource="{Binding YourCollection}" SelectedItem="{Binding
YourCollection.CurrentItem}" />
属性的属性才能工作。就我的例子而言,我有这个:
{{1}}
答案 1 :(得分:5)
展开Bolu's comment,您可以使用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
现已绑定到ViewModel中的SelectedItemProperty
。
答案 2 :(得分:1)
bigworld12在这里接近正确的答案,但如果您的上下文菜单是模板化的,它会中断。尝试:
DataGridRow row =
((sender as MenuItem)?.GetAncestors()
?.FirstOrDefault(dpo => dpo.GetType() == typeof(ContextMenu)) as ContextMenu)
?.PlacementTarget as DataGridRow;
代码隐藏。我使用了可空运算符,以防你以某种方式到达这里而没有预期的父树和目标(可能是在离开网格时触发上下文菜单。)
答案 3 :(得分: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
答案 4 :(得分: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>.