在 WPF 中,是否可以将 ItemsControl 的 ItemContainerGenerator.StatusChanged 事件作为 MVVM 模式命令获取?

In WPF, is it possible to get the ItemContainerGenerator.StatusChanged event of an ItemsControl as an MVVM pattern command?

在 WPF 中,是否可以将 ItemsControl 的 ItemContainerGenerator.StatusChanged 事件作为 MVVM 模式命令获取?

可以直接获取ItemsControl并注册StatusChanged事件 我想知道是否可以在不直接访问的情况下以 MVVM 模式实现 ItemsControl。

试试这个:

public class ItemContainerGeneratorBehavior
{
    public static Dictionary<ItemsControl, EventHandler> HandlersMap = new Dictionary<ItemsControl, EventHandler>();
    public static Dictionary<ItemsControl, GeneratorStatus> StatusMap = new Dictionary<ItemsControl, GeneratorStatus>();

    public static ICommand GetStatusCommand(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(StatusCommandProperty);
    }

    public static void SetStatusCommand(DependencyObject obj, ICommand value)
    {
        obj.SetValue(StatusCommandProperty, value);
    }

    // Using a DependencyProperty as the backing store for StatusCommand.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty StatusCommandProperty =
        DependencyProperty.RegisterAttached("StatusCommand", typeof(ICommand), typeof(ItemContainerGeneratorBehavior),
            new PropertyMetadata(null, OnStatusCommandChanged));

    private static void OnStatusCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var itemsControl = d as ItemsControl;
        if (itemsControl == null)
            return;
        if (e.OldValue != null)
        {
            if (HandlersMap.ContainsKey(itemsControl))
            {
                itemsControl.ItemContainerGenerator.StatusChanged -= HandlersMap[itemsControl];
                HandlersMap.Remove(itemsControl);
                StatusMap.Remove(itemsControl);
            }
        }
        if (e.NewValue != null)
        {
            HandlersMap[itemsControl] = (_d, _e) => ItemContainerGenerator_StatusChanged(itemsControl, _e);
            StatusMap[itemsControl] = itemsControl.ItemContainerGenerator.Status;
            itemsControl.ItemContainerGenerator.StatusChanged += HandlersMap[itemsControl];
        }
    }

    private static void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
    {
        var itemsControl = sender as ItemsControl;
        if (itemsControl == null)
            return;
        var commandHandler = GetStatusCommand(itemsControl);
        var status = itemsControl.ItemContainerGenerator.Status;
        var args = new StatusChangedArgs(StatusMap[itemsControl], status);
        StatusMap[itemsControl] = status;
        if (commandHandler.CanExecute(args))
            commandHandler.Execute(args);
    }
}

...然后您可以在 ItemsControl 样式中使用...

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.Style>
        <Style TargetType="{x:Type ItemsControl}" BasedOn="{StaticResource {x:Type ItemsControl}}">
            <Setter Property="behaviors:ItemContainerGeneratorBehavior.StatusCommand" Value="{Binding RelativeSource={RelativeSource Self}, Path=DataContext.StatusChangedCommand}" />
        </Style>
    </ItemsControl.Style>
</ItemsControl>

...并在您的视图模型中处理...

    private ICommand _StatusChangedCommand;
    public ICommand StatusChangedCommand => this._StatusChangedCommand ?? (this._StatusChangedCommand = new RelayCommand<StatusChangedArgs>(OnStatusChanged));

    private void OnStatusChanged(StatusChangedArgs args)
    {
        // do something here
    }

您还需要这个:

public class StatusChangedArgs
{
    public GeneratorStatus OldStatus { get; private set; }
    public GeneratorStatus NewStatus { get; private set; }

    public StatusChangedArgs(GeneratorStatus oldStatus, GeneratorStatus newStatus)
    {
        this.OldStatus = oldStatus;
        this.NewStatus = newStatus;
    }

    public override string ToString()
    {
        return $"{this.OldStatus} -> {this.NewStatus}";
    }
}