DataGrid WPF虚拟化和命令CanExecute

时间:2013-11-14 15:47:57

标签: wpf wpfdatagrid icommand ui-virtualization

我正在使用框架.NET 4.0

开发WPF应用程序

我的DataGrid有问题:每行都有2个命令:

public ICommand MoveUpOrderPipeCommand
{
     get
     {
         if (_moveUpOrderPipeCommand == null)
         {
              _moveUpOrderPipeCommand = new Command<OrderPipeListUIModel>(OnMoveUpOrderPipe, CanMoveUpOrderPipe);
         }
                return _moveUpOrderPipeCommand;
      }
}

private bool CanMoveUpOrderPipe(OrderPipeListUIModel orderPipe)
{
     if (OrderPipes == null || !OrderPipes.Any() || OrderPipes.First() == orderPipe)
          return false;
     return true;
}

MoveDown有相同的命令(可以执行检查该行是否不是最后一行)

DataGrid:

<DataGrid Grid.Row="1" IsReadOnly="True" ItemsSource="{Binding OrderPipes}" SelectionMode="Extended">
   <DataGrid.Columns>
      <DataGridTextColumn Header="Diam. (mm)" Binding="{Binding Diameter}" Width="120">    </DataGridTextColumn>
      <DataGridTextColumn Header="Lg. (m)" Binding="{Binding Length}" Width="120"></DataGridTextColumn>
      <DataGridTextColumn Header="Ep. (mm)" Binding="{Binding Thickness}" Width="120"></DataGridTextColumn>
      <DataGridTextColumn Header="Ondulation" Binding="{Binding Ripple}" Width="120"></DataGridTextColumn>
      <DataGridTemplateColumn>
         <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
               <StackPanel Orientation="Horizontal">
                  <Button Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.MoveUpOrderPipeCommand}" CommandParameter="{Binding}">
                  </Button>
               </StackPanel>
            </DataTemplate>
         </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
   </DataGrid.Columns>
</DataGrid>

如果我使用EnableRowVirtualization将我的网格虚拟化为true,我会遇到一些麻烦,如果我滚动到底部(第一行不再可见)然后滚动回到顶部,有时第一行的按钮会移动(normaly can' t up up)启用,直到我点击DataGrid,并且第二个或第三个被禁用,应启用!

如果我将EnableRowVirtualization设置为false,我没有这个问题...

我只在互联网上找到另一篇关于这个问题的帖子,但是没有来自.net框架的dataGrid: http://www.infragistics.com/community/forums/t/15189.aspx

你知道我该如何解决它?

提前谢谢

编辑:命令类

public class Command<T> : ICommand
{
    private readonly Action<T> _execute;
    private readonly Func<T, bool> _canExecute;

    public Command(Action<T> execute) : this(execute, null)
    {
    }

    public Command(Action<T> execute, Func<T, bool> canExecute)
    {
       if (execute == null)
          throw new ArgumentNullException("execute", "Le délégué execute ne peut pas être nul");

       this._execute = execute;
       this._canExecute = canExecute;
    }

    public event EventHandler CanExecuteChanged
    {
       add
       {
          CommandManager.RequerySuggested += value;
       }
       remove
       {
          CommandManager.RequerySuggested -= value;
       }
    }

    public bool CanExecute(object parameter)
    {
       return (_canExecute == null) ? true : _canExecute((T)parameter);
    }

    public void Execute(object parameter)
    {
       _execute((T)parameter);
    }
 }

1 个答案:

答案 0 :(得分:4)

问题是当您使用鼠标滚轮滚动时,不会调用canExecute。

我创建了一个AttachedProperty来纠正这个问题,它可以用在一个样式中。

public static readonly DependencyProperty CommandRefreshOnScrollingProperty = DependencyProperty.RegisterAttached(
            "CommandRefreshOnScrolling", 
            typeof(bool), 
            typeof(DataGridProperties), 
            new FrameworkPropertyMetadata(false, OnCommandRefreshOnScrollingChanged));

private static void OnCommandRefreshOnScrollingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
      var dataGrid = d as DataGrid;
      if (dataGrid == null)
      {
          return;
      }
      if ((bool)e.NewValue)
      {
         dataGrid.PreviewMouseWheel += DataGridPreviewMouseWheel;
      }
}
private static void DataGridPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
     CommandManager.InvalidateRequerySuggested();
}

你可以像这样使用这个attachProperty:

    <Setter Property="views:DataGridProperties.CommandRefreshOnScrolling" Value="True"></Setter>

感谢Eran Otzap告诉我为什么会遇到这个问题!