【发布时间】:2017-05-12 11:02:25
【问题描述】:
更新!!! 我发现当我将它放入 DataGrid 时,即使这也不起作用:
<DataGrid.ContextMenu>
<ContextMenu >
<MenuItem Header="Add Divider" Click="MenuItem_Click" />
</ContextMenu>
</DataGrid.ContextMenu>
这绝对适用于从头开始设置的虚拟项目。所以我不认为我遇到了绑定问题或数据上下文问题......我还没有走那么远。我怀疑程序的其他部分正在拦截和处理上下文菜单(或右键单击)。我没有编写原始代码,它是一个庞大的代码库。有人可以告诉我我应该寻找什么吗?什么会阻止调用 DataGrid 上的 ContextMenu。请注意,DataGrid 位于 ScrollViewer 和 StackPanel 中,整个控件是较大窗口的一部分。事实上,它只是众多标签之一。
-结束更新
我正在努力在我的 WPF/MVVM 项目中的 DataGrid 上获取上下文菜单。我在下面发布了 XAML 和 ViewModel。我希望能够右键单击一行并在 ViewModel 中调用一个命令,该命令将更改该行的一个列条目。
XAML(我在下面列出我认为的关键点)
<UserControl x:Class="Sears.UserInterface.Views.Technician.Alerts.AlertsLogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Sears.UserInterface.Views.Technician.Alerts"
xmlns:converters="clr-namespace:Common.Controls.Converters;assembly=Common.Controls"
mc:Ignorable="d"
d:DesignHeight="800"
d:DesignWidth="1200">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" />
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<ScrollViewer>
<DataGrid Width="1000"
Margin="0"
HorizontalAlignment="Left"
AutoGenerateColumns="False"
Background="Transparent"
DataContext="{Binding}"
HeadersVisibility="Column"
ItemsSource="{Binding Alerts}"
SelectedItem="{Binding SelectedItemProperty, Mode=TwoWay}"
RowBackground="Transparent"
RowHeight="30"
Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}"
>
**<DataGrid.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Command="{Binding CloseAlertCommand}" Header="Close Alert"/>
</ContextMenu>
</DataGrid.ContextMenu>**
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="FontWeight" Value="Bold" />
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>
<DataGridTemplateColumn Width="*" Header="Id">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Id}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="TimeStamp">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding AlertTime}" >
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Severity">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Severity}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="AlertText">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding AlertText}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Details">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Details}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Active">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Active}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Acknowledged">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Acknowledged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Reported">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Reported}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Status">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Status}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Resolution">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Resolution}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Category">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
Padding="5"
Text="{Binding Category}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
</StackPanel>
注意 DataGrid.ContextMenu 部分。我搜索了 StackOverflow 并尝试了各种想法来显示上下文菜单。没有。此特定示例使用“标签”。我还尝试将上下文菜单放在资源部分中:
<ContextMenu x:Key="DataRowContextMenu" DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=DataGrid, Mode=FindAncestor}}">
<MenuItem x:Name="RowContMenuTransfer" Header="Close Alert" Command="{Binding DataContext.CloseAlertCommand}" CommandParameter="{Binding}" >
</MenuItem>
</ContextMenu>
执行此操作的“标记”方式不会导致绑定错误。你只需右键单击,什么都没有!其他方式(我可以发布)在输出窗口中给出了绑定错误。可能值得注意的是,DataGrid 位于 ScrollViewer 和 StackPanel 中。
这是视图模型
public class AlertsLogViewModel : ViewModelBase, IAlertsLogViewModel, IDisposable
{
private IAlertManager _model;
private readonly object _lock = new object();
private ICommand _closeAlertCommand;
public AlertsLogViewModel(IAlertManager model) : base("AlertsLogViewModel")
{
Alerts = new ObservableCollection<IAlert>();
_model = model ?? throw new ArgumentNullException("model");
_model.AlertStatusUpdated += _model_AlertStatusUpdated;
UpdateAlerts();
}
public IAlert SelectedItemProperty { get; set; }
public ICommand CloseAlertCommand
{
get { return _closeAlertCommand ?? (_closeAlertCommand = new DelegateCommand(CloseAlert)); }
}
private void CloseAlert()
{
_model.CloseAlert(SelectedItemProperty.SystemErrorGuid);
}
public ObservableCollection<IAlert> Alerts { get; private set; }
private void _model_AlertStatusUpdated(object sender, DataAccess.AlertStatusEventArgs e)
{
UpdateAlerts();
}
private void UpdateAlerts()
{
RunOnDispatcher(() =>
{
lock (_lock)
{
var modelAlerts = _model.GetAlerts().OrderBy(p => (int)p.Status).ThenByDescending(p => p.AlertTime);
Alerts.Clear();
if (modelAlerts != null)
{
foreach (var alert in modelAlerts)
{
Alerts.Add(alert);
}
}
}
}
);
NotifyPropertyChanged("Alerts");
}
public void Dispose()
{
if (_model != null)
_model.AlertStatusUpdated -= _model_AlertStatusUpdated;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
注意 CloseAlertCommand 和 SelectedItemProperty。我确实看到当我左键单击而不是右键单击时调用了 SelectedItemProperty。 CloseAlert 永远不会被调用。
最后,如果它是相关的,让我提一下 AlertsLogView 在 Technicial.xaml 页面内,它在这里绑定到 ViewModel:
<TabItem Header="Alerts"
PreviewMouseDown="OnPreviewMouseDown"
PreviewTouchDown="OnPreviewTouchDown">
<alertlog:AlertsLogView Margin="5"
DataContext="{Binding AlertsLogViewModel}" />
</TabItem>
非常感谢任何提示、参考、指针或解决方案!
-戴夫
【问题讨论】:
-
在简化形式中,您的代码对我有用。尝试将 Header 而非命令绑定到 VM 中的某个属性,看看它是否有价值。可能是,你有死锁吗?你使用 lock()..
-
有趣。你能告诉(或分享)简化代码是什么吗?你必须拿出什么?感谢您阅读我的问题!
-
Rekshino,我删除了 Command 绑定,并从 Header(ContextMenu 中的 MenuItem 到 ViewModel 属性)中放入了绑定。不走运。
-
您是否尝试过检查您的 MenuItem 有哪些 ViewModel(如果您在绑定中放置转换器并在其中设置制动点,您可以做到这一点)?我已将用户控件直接放在窗口中(而不是 TabItem),并从窗口的静态资源中设置 DataContext。用户控件几乎相同,MenuItem 的绑定相同。你说,所选项目的绑定有效?!嗯..奇怪..
-
谢谢。看我更新。我认为有些东西甚至阻止了上下文菜单被调用。也许右键在其他地方被拦截了?
标签: wpf mvvm binding datagrid contextmenu