阻止用户在WPF DataGrid中选择/取消选择行

时间:2013-04-25 14:32:51

标签: wpf datagrid selection

我在WPF页面上有一个DataGrid,并希望阻止用户选择单元格。由于此功能仅用于测试,我不想更改代码中的所有内容。

填写DataGrid后,我确保选中所有行。现在我想确保用户无法选择/取消选择行。

我尝试设置IsEnabled = falseIsHitTestVisible = "False",但这两种解决方案都禁用了滚动条。

有没有办法做到这一点?

2 个答案:

答案 0 :(得分:10)

为什么不仅为IsHitTestVisible="False"DataGridRow个对象设置DataGridCell

使用<DataGrid.Resources>中的隐式样式很容易做到,并且应该只对行或单元格禁用命中测试,这应该使DataGrid的其他区域保持功能,例如标题或滚动条

<DataGrid.Resources>
    <Style TargetType="{x:Type DataGridRow}">
        <Setter Property="IsHitTestVisible" Value="False" />
    </Style>
</DataGrid.Resources>

答案 1 :(得分:0)

您有两种选择:

  1. 您在样式中禁用选择(在这种情况下,您只关闭样式中的颜色,但物理SelectedItem或SelectedItems将更改)。您可以轻松了解如何关闭选择方式。

  2. 您可以在不更改SelectedItem或SelectedItems的情况下禁用更改选择(在这种情况下,您的选择样式也不会更改)。

  3. 在WPF中,我不想覆盖标准控件。所以,我们需要一个Behavior

    public class DisableSelectionDataGridBehavior : Behavior<DataGrid>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObjectOnPreviewMouseLeftButtonDown;
        }
    
        private void AssociatedObjectOnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var dependencyObject = AssociatedObject.InputHitTest(e.GetPosition(AssociatedObject)) as DependencyObject;
            if (dependencyObject == null) return;
    
            var elements = dependencyObject.GetParents().OfType<FrameworkElement>().Where(DataGridCellExtended.GetIsDisableSelection).ToList();
            if (!elements.Any()) return;
    
            e.Handled = true;
    
            var args = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.ChangedButton, e.StylusDevice);
            args.RoutedEvent = UIElement.MouseLeftButtonDownEvent;
            args.Source = e.Source;
    
            elements.ForEach(item =>
            {
                item.RaiseEvent(args);
                var children = item.GetChildren<FrameworkElement>();
                children.ForEach(child => child.RaiseEvent(args));
            });
        }
    
        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObjectOnPreviewMouseLeftButtonDown;
        }
    }
    

    其次,您需要一个Extended类:

    public class DataGridCellExtended
    {
        public static readonly DependencyProperty IsDisableSelectionProperty = DependencyProperty.RegisterAttached("IsDisableSelection", typeof(Boolean), typeof(DataGridCellExtended));
    
        public static Boolean GetIsDisableSelection(DependencyObject o)
        {
            return (Boolean)o.GetValue(IsDisableSelectionProperty);
        }
    
        public static void SetIsDisableSelection(DependencyObject o, Boolean value)
        {
            o.SetValue(IsDisableSelectionProperty, value);
        }
    }
    

    最后在XAML中你需要这样的东西:

    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate DataType="{x:Type items:YourViewModel}">
            <StackPanel Orientation="Horizontal"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center">
                <Button Margin="0"
                        extends:DataGridCellExtended.IsDisableSelection="True">
    
                    <Path Data="M5,0L3,2 1,0 0,1 2,3 0,5 1,6 3,4 5,6 6,5 4,3 6,1z"
                          Fill="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridCell}}"
                          Width="12"
                          Height="12"
                          Stretch="Uniform"/>
                </Button>
            </StackPanel>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    

    您可以为扩展类编写逻辑。

    public static IEnumerable<DependencyObject> GetParents(this DependencyObject element)
    {
        if (element != null)
        {
            while (true)
            {
                var parent = element.GetParent();
                var dependencyObject = parent;
                element = parent;
                if (dependencyObject == null)
                {
                    break;
                }
                yield return element;
            }
            yield break;
        }
        else
        {
            throw new ArgumentNullException("element");
        }
    }
    
    private static IEnumerable<DependencyObject> GetChildrenRecursive(this DependencyObject element)
    {
        if (element != null)
        {
            for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
            {
                var dependencyObject = VisualTreeHelper.GetChild(element, i);
                yield return dependencyObject;
                foreach (var childrenRecursive in dependencyObject.GetChildrenRecursive())
                {
                    yield return childrenRecursive;
                }
            }
        }
        else
        {
            throw new ArgumentNullException("element");
        }
    }