MVVM - WPF DataGrid - AutoGeneratingColumn Event

时光毁灭记忆、已成空白 提交于 2019-12-04 18:04:54

During the course of developing a project with MVVM you're going to have circumstances where you must handle events in your view's code-behind and EventToCommand just plain doesn't work. You especially find this with Silverlight, but I assume from your question that you're using WPF. It's okay to do some event handling in your view's code-behind, just don't put any business logic there. You can even leave the command in your view model, just call it directly from your event handler.

((YourViewModel)this.DataContext).rcAutoGeneratingColumn.Execute(sender);

You don't have to use evil code behind ;-) You can do this using an attached behaviour...

public class AutoGeneratingColumnEventToCommandBehaviour
{
    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.RegisterAttached(
            "Command", 
            typeof(ICommand), 
            typeof(AutoGeneratingColumnEventToCommandBehaviour),
            new PropertyMetadata(
                null,
                CommandPropertyChanged));

    public static void SetCommand(DependencyObject o, ICommand value)
    {
        o.SetValue(CommandProperty, value);
    }

    public static ICommand GetCommand(DependencyObject o)
    {
        return o.GetValue(CommandProperty) as ICommand;
    }

    private static void CommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = d as DataGrid;
        if (dataGrid != null)
        {
            if (e.OldValue != null)
            {
                dataGrid.AutoGeneratingColumn -= OnAutoGeneratingColumn;
            }
            if (e.NewValue != null)
            {
                dataGrid.AutoGeneratingColumn += OnAutoGeneratingColumn;
            }
        }
    }

    private static void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        var dependencyObject = sender as DependencyObject;
        if (dependencyObject != null)
        {
            var command = dependencyObject.GetValue(CommandProperty) as ICommand;
            if (command != null && command.CanExecute(e))
            {
                command.Execute(e);
            }
        }
    }
}

Then use it in XAML like this...

<DataGrid ItemsSource="{Binding MyGridSource}"
          AttachedCommand:AutoGeneratingColumnEventToCommandBehaviour.Command="{Binding CreateColumnsCommand}">
</DataGrid>

Just set EventTrigger.SourceObject property.

<DataGrid
  x:Name="DataGrid"
  AutoGenerateColumns="True"
  IsReadOnly="True"
  ItemsSource="{Binding Data}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="AutoGeneratingColumn" SourceObject="{Binding ElementName=DataGrid}">
      <local:EventToCommand
        Command="{Binding ColumnGeneratingCommand}"
        PassEventArgsToCommand="True" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</DataGrid>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!