问题
In the XAML below, the command property is correctly working only with Column B. Clicking on Column A's header is not invoking command's execute method. The difference is that in Column B, DataGridColumnHeader is instantiated explicitly.
On other hand, the second part of style, the trigger that sets background base on Pressed state is working for both columns.
Why does the Command property work with Column B & not with Column A ?
<DataGrid x:Name="Test"
ItemsSource="{Binding Items}"
AutoGenerateColumns="False" >
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Command"
Value="{Binding MyCommand}"/>
<Setter Property="CommandParameter"
Value="{Binding Path=Content, RelativeSource={RelativeSource Self}}"/>
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>
<DataGridTextColumn FontSize="12"
Header="Column A"
Width="200"
Binding="{Binding AData}" />
<DataGridTextColumn FontSize="12"
Width="200"
Binding="{Binding BData}">
<DataGridTextColumn.Header>
<DataGridColumnHeader Content="Column B" />
</DataGridTextColumn.Header
>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
EDIT
Data context:
namespace TestColumnHeaderCommandBinding
{
public class Item
{
public int AData { get; set; }
public string BData { get; set; }
}
public class MyCommand : ICommand
{
#region ICommand Members
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
MessageBox.Show(parameter.ToString() + " clicked");
}
#endregion
}
public class DataContext
{
public DataContext()
{
MyCommand = new TestColumnHeaderCommandBinding.MyCommand();
Items = new List<Item>(5);
Items.Add(new Item { AData = 1, BData = "One" });
Items.Add(new Item { AData = 2, BData = "Two" });
Items.Add(new Item { AData = 3, BData = "Three" });
Items.Add(new Item { AData = 4, BData = "Four" });
Items.Add(new Item { AData = 5, BData = "Five" });
}
public MyCommand MyCommand { get; set; }
public List<Item> Items { get; set; }
}
}
回答1:
If you don't explicitly specify the content of the header, it will just contain a simple string, which will not inherit the DataContext
of the containing DataGrid
.
You should see a warning in the Visual Studio output window containing something like this:
'MyCommand' property not found on 'object' ''String'
To fix that, you can make the binding target the DataContext
of the DataGrid
:
<Setter Property="Command"
Value="{Binding DataContext.MyCommand,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
来源:https://stackoverflow.com/questions/20748631/datagrid-columnheaderstyle-and-command-binding