我正在尝试为特定于标头的WPF数据网格构建上下文菜单(换句话说,每个列标题可以使其自己的上下文菜单与其他标题不同)。 此外,支持上下文菜单的数据是绑定数据。 我的问题是我似乎无法将菜单连接到我的数据上下文。 我从这里和其他地方尝试过一些建议,但到目前为止还没有运气。
我知道上下文菜单不在文档其余部分的可视树中,所以我尝试使用它的PlacementTarget(如下所示)但是当我点击列标题时,我的PlacementTarget只是标题的TextBlock。我如何从那里到达网格的DataContext?
这是我尝试过的一个例子:
<Window x:Class="ContextMenuExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ContextMenuExample"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ExampleViewModel />
</Window.DataContext>
<Grid>
<DataGrid ItemsSource="{Binding MyGridData}" IsReadOnly="True" AutoGenerateColumns="False">
<!-- THESE WORK, BUT THEY ARE GRID-GLOBAL. I WANT HEADER-SPECIFIC CONTEXT MENUS -->
<DataGrid.ContextMenu>
<ContextMenu>
<CheckBox Name="GridCheckbox1" Content="Grid Menu - Item1" IsChecked="{Binding Column1Checked, Mode=TwoWay}"/>
<CheckBox Name="GridCheckbox2" Content="Grid Menu - Item2" IsChecked="{Binding Column2Checked, Mode=TwoWay}"/>
<CheckBox Name="GridCheckbox3" Content="Grid Menu - Item3" IsChecked="{Binding Column3Checked, Mode=TwoWay}"/>
</ContextMenu>
</DataGrid.ContextMenu>
<DataGrid.Columns>
<DataGridTextColumn Header="Column 1 Data" Binding="{Binding Column1Data}" Width="Auto">
<!-- ATTEMPT 1 - JUST SEE IF I CAN BIND DIRECTLY. SHOULDN'T WORK. -->
<!-- System.Windows.Data Error: 40 : BindingExpression path error: 'Column1Checked' property not found on 'object' ''String' (HashCode=-1586790989)'. BindingExpression:Path=Column1Checked; DataItem='String' (HashCode=-1586790989); target element is 'CheckBox' (Name='Header1Checkbox'); target property is 'IsChecked' (type 'Nullable`1') -->
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Name="Header1TextBlock" Text="{TemplateBinding Content}" >
<TextBlock.ContextMenu>
<ContextMenu>
<CheckBox Name="Header1Checkbox" Content="Header Menu 1" IsChecked="{Binding Column1Checked, Mode=TwoWay}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
<DataGridTextColumn Header="Column 2 Data" Binding="{Binding Column1Data}" Width="Auto">
<!-- ATTEMPT 2 - BIND TO THE PLACEMENT TARGET. THIS MAKES THE TextBlock MY DATA CONTEXT. CLOSER (?) BUT STILL WRONG -->
<!-- System.Windows.Data Error: 40 : BindingExpression path error: 'Column2Checked' property not found on 'object' ''TextBlock' (Name='Header2TextBlock')'. BindingExpression:Path=Column2Checked; DataItem='TextBlock' (Name='Header2TextBlock'); target element is 'CheckBox' (Name='Header2Checkbox'); target property is 'IsChecked' (type 'Nullable`1') -->
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Name="Header2TextBlock" Text="{TemplateBinding Content}" >
<TextBlock.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
<CheckBox Name="Header2Checkbox" Content="Header Menu 2" IsChecked="{Binding Column2Checked, Mode=TwoWay}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
<DataGridTextColumn Header="Column 3 Data" Binding="{Binding Column1Data}" Width="Auto">
<!-- ATTEMPT 3 - BIND TO THE PLACEMENT TARGETS' CONTEXT. I'M NOT EVEN SURE WHAT THIS IS, BUT IT DOESN'T WORK -->
<!-- System.Windows.Data Error: 40 : BindingExpression path error: 'Column3Checked' property not found on 'object' ''String' (HashCode=975011251)'. BindingExpression:Path=Column3Checked; DataItem='String' (HashCode=975011251); target element is 'CheckBox' (Name='Header3Checkbox'); target property is 'IsChecked' (type 'Nullable`1') -->
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Name="Header3TextBlock" Text="{TemplateBinding Content}" >
<TextBlock.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<CheckBox Name="Header3Checkbox" Content="Header Menu 3" IsChecked="{Binding Column3Checked, Mode=TwoWay}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
class GridData
{
public int Column1Data { get; set; }
public int Column2Data { get; set; }
public int Column3Data { get; set; }
}
class ExampleViewModel : INotifyPropertyChanged
{
private bool column1Checked;
private bool column2Checked;
private bool column3Checked;
public event PropertyChangedEventHandler PropertyChanged;
public List<GridData> MyGridData
{
get
{
return new List<GridData>
{
new GridData() { Column1Data = 1, Column2Data = 2, Column3Data = 3},
new GridData() { Column1Data = 4, Column2Data = 5, Column3Data = 6},
new GridData() { Column1Data = 7, Column2Data = 8, Column3Data = 9}
};
}
}
public bool Column1Checked
{
get { return column1Checked; }
set {
if (column1Checked != value)
{
column1Checked = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Column1Checked)));
}
}
}
public bool Column2Checked
{
get { return column2Checked; }
set {
if (column2Checked != value)
{
column2Checked = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Column2Checked)));
}
}
}
public bool Column3Checked
{
get { return column3Checked; }
set {
if (column3Checked != value)
{
column3Checked = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Column3Checked)));
}
}
}
}
所以我的问题是......如何将我的上下文菜单绑定到我的ViewModel?
感谢您提供的任何帮助。
答案 0 :(得分:0)
试试这个。
$ip = $_SERVER['REMOTE_ADDR'];
$mac=shell_exec("arp -a ".$ip);
$mac_string = shell_exec("arp -a $ip");
$mac_array = explode(" ",$mac_string);
$mac = $mac_array[3];
if(empty($mac)) {
die("No mac address for $ip not found");
}
echo($ip." - ".$mac);
我不太确定它是否有效,因为你的<DataGridTextColumn Header="Column 1 Data" Binding="{Binding Column1Data}" Width="Auto">
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Name="Header1TextBlock" Text="{TemplateBinding Content}">
<TextBlock.ContextMenu>
<ContextMenu>
<CheckBox Name="Header1Checkbox" Content="Header Menu 1" IsChecked="{Binding DataContext.Column1Checked, RelativeSource={RelativeSource AncestorType=Window}, Mode=TwoWay}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
是在模板中定义的。
答案 1 :(得分:0)
我终于找到了我需要的东西:
WPF ContextMenu woes: How do I set the DataContext of the ContextMenu?
感谢daub815
这对我有用:
<DataGridTextColumn Header="Column 1 Data" Binding="{Binding Column1Data}" Width="Auto">
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Name="Header1TextBlock" Text="{TemplateBinding Content}" Tag="{Binding DataContext, ElementName=MyDataGrid}">
<TextBlock.ContextMenu>
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<CheckBox Name="Header1Checkbox" Content="Header Menu 1" IsChecked="{Binding Column1Checked, Mode=TwoWay}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
(MyDataGrid是DataGrid对象的地方)