2

私はDataGridWPF ページ上にあり、ユーザーがセルを選択できないようにしたいと考えています。この機能はテストのためだけに必要なので、コードのすべてを変更したくありません。

が入力されたらDataGrid、そのすべての行が選択されていることを確認します。ここで、ユーザーが行を選択/選択解除できないようにしたいと考えています。

IsEnabled = false設定を試みIsHitTestVisible = "False"ましたが、これらのソリューションは両方ともスクロールバーを無効にします。

これを行う方法はありますか?

4

2 に答える 2

10

またはオブジェクトのみに設定IsHitTestVisible="False"しないのはなぜですか?DataGridRowDataGridCell

これは、 で暗黙的なスタイルを使用して簡単に実行できます<DataGrid.Resources>。また、行またはセルのヒット テストのみを無効にする必要があります。これによりDataGrid、ヘッダーやスクロール バーなどの機能の他の領域を残す必要があります。

<DataGrid.Resources>
    <Style TargetType="{x:Type DataGridRow}">
        <Setter Property="IsHitTestVisible" Value="False" />
    </Style>
</DataGrid.Resources>
于 2013-04-25T16:18:36.900 に答える
-1

次の 2 つの選択肢があります。

  1. スタイルの選択を無効にします (この場合、スタイルの色のみをオフにしますが、物理的に SelectedItem または SelectedItems が変更されます)。選択スタイルをオフにする方法を簡単に見つけることができます。

  2. SelectedItem または SelectedItems を変更せずに選択の変更を無効にすることができます (この場合、選択スタイルも変更されません)。

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");
    }
}
于 2015-01-14T09:36:58.317 に答える