如何获取事件发射项控件的数据上下文?

How to get datacontext of an event emitting item control?

我在 items control 中渲染了一堆按钮。我想访问单击按钮的 data context。我怎样才能做到这一点?

型号:

public class RunYear
{
    public RunYear(int year)
    {
        Year = year;
        Months = new Month[3];
    }
    public int Year { get; set; }
    public Month[] Months { get; set; }
}

public class Month
{
    public int ColumnIndex { get; set; }
    public string MonthName { get; set; }
    // some other props
}

后面的代码:

public partial class MainWindow : Window
{
    private ObservableCollection<RunYear> _years = new ObservableCollection<RunYear>();
    public ObservableCollection<RunYear> Years { get{return _years; } }
    public MainWindow()
    {
        DataContext = this;
        InitializeComponent();
        GenerateData();
    }

    private void GenerateData()
    {
        for (int i = 2010; i < 2015; i++)
        {
            var runYear = new RunYear(i);
            runYear.Months[0] = new Month() { ColumnIndex = 0, MonthName = $"Jan {i}" };
            runYear.Months[1] = new Month() { ColumnIndex = 1, MonthName = $"Feb {i}" };
            runYear.Months[2] = new Month() { ColumnIndex = 2, MonthName = $"Mar {i}" };
            Years.Add(runYear);
        }
    }

    public void OnClick(object sender, RoutedEventArgs args)
    {
        // how do I get the databound item?
        var cp = sender as ContentPresenter; //doesn't work
        var vm = cp?.Content as Month;
    }
}

XAML:

    <Grid>
    <ItemsControl Name="icYears" ItemsSource="{Binding Years}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="70" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="75"/>
                    </Grid.RowDefinitions>
                    <DockPanel Grid.Column="0" Grid.Row="0" >
                        <TextBox IsReadOnly="True" TextAlignment="Center" Text="{Binding Year}" />
                    </DockPanel>

                    <ItemsControl Grid.Column="1" Name="icMonths" ItemsSource="{Binding Months}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <Grid >
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*" />
                                        <ColumnDefinition Width="*" />
                                        <ColumnDefinition Width="*" />
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="75"></RowDefinition>
                                    </Grid.RowDefinitions>
                                </Grid>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemContainerStyle>
                            <Style>
                                <Setter Property="Grid.Column" Value="{Binding ColumnIndex}" />
                            </Style>
                        </ItemsControl.ItemContainerStyle>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Button Click="OnClick"  Content="{Binding MonthName}"  Padding="2" Margin="2"/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

你是这个意思吗?

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    var vm = (sender as FrameworkElement).DataContext;