17

DataGrid全体または列全体をreadyonly(IsReadOnly = true)にすることができることを理解しています。ただし、セルレベルでは、このプロパティは準備ができているだけです。しかし、私はこのレベルの粒度が必要です。DataGridがパブリックドメインだった昔のソースコードを変更してIsReadOnlyを行に追加することについてのブログがありますが、現在はDataGridのソースコードがありません。回避策は何ですか?

セルを無効にする(IsEnabled = false)と、ほぼ私のニーズが満たされます。ただし、問題は、無効になっているセルをクリックして行を選択することさえできないことです(私は完全な行選択モードを使用しています)。

編集:誰もこの質問に答えていないので、簡単な修正ではないと思います。考えられる回避策は次のとおりです。セルを編集不可にします。唯一の問題は、セルをクリックしても行が選択されないことです。無効にされたセルがクリックされたときに、DataGridのMouseDownまたはMouseUpイベントがまだ発生していることに気づきました。このイベントハンドラーでは、クリックした行を把握できれば、プログラムで行を選択できます。ただし、から基になる行を見つける方法がわかりませんでしたDataGrid.InputHitTest。誰かが私にいくつかのヒントを教えてもらえますか?

4

11 に答える 11

13

IsTabStop=FalseとFocusable=Falseを使用して多くの検索と実験を行った後、私には最適です。

<DataGridTextColumn Header="My Column" Binding="{Binding Path=MyColumnValue}">
    <DataGridTextColumn.CellStyle>
        <Style TargetType="DataGridCell">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=ReadOnly}" Value="True">
                    <Setter Property="IsTabStop" Value="False"></Setter>
                    <Setter Property="Focusable" Value="False"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>
于 2015-09-09T07:57:02.140 に答える
12

同じ問題が発生しました。セルは一部の行では読み取り専用である必要がありますが、他の行では読み取り専用ではありません。回避策は次のとおりです。

アイデアは、2つのテンプレートを動的に切り替えることですCellEditingTemplate。1つはのテンプレートと同じで、もう1つはCellTemplate編集用です。これにより、編集モードは編集モードではありますが、非編集セルとまったく同じように機能します。

以下は、これを行うためのサンプルコードです。このアプローチには、次のものが必要であることに注意してDataGridTemplateColumnください。

まず、読み取り専用セルと編集セルの2つのテンプレートを定義します。

<DataGrid>
  <DataGrid.Resources>
    <!-- the non-editing cell -->
    <DataTemplate x:Key="ReadonlyCellTemplate">
      <TextBlock Text="{Binding MyCellValue}" />
    </DataTemplate>

    <!-- the editing cell -->
    <DataTemplate x:Key="EditableCellTemplate">
      <TextBox Text="{Binding MyCellValue}" />
    </DataTemplate>
  </DataGrid.Resources>
</DataGrid>

ContentPresenter次に、追加のレイヤーを使用してデータテンプレートを定義し、を使用Triggerしてのを切り替えます。これContentTemplateにより、上記の2つのテンプレートをバインディングContentPresenterによって動的に切り替えることができます。IsEditable

<DataGridTemplateColumn CellTemplate="{StaticResource ReadonlyCellTemplate}">
  <DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
      <!-- the additional layer of content presenter -->
      <ContentPresenter x:Name="Presenter" Content="{Binding}" ContentTemplate="{StaticResource ReadonlyCellTemplate}" />
      <DataTemplate.Triggers>
        <!-- dynamically switch the content template by IsEditable binding -->
        <DataTrigger Binding="{Binding IsEditable}" Value="True">
          <Setter TargetName="Presenter" Property="ContentTemplate" Value="{StaticResource EditableCellTemplate}" />
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

HTH

于 2011-08-19T02:21:05.380 に答える
11

たとえば、次のようなXAMLを使用DataGridCell.IsReadOnlyして、バインドできると思われるプロパティがあります。

<!-- Won't work -->
<DataGrid Name="myDataGrid" ItemsSource="{Binding MyItems}">
    <DataGrid.Resources>
        <Style TargetType="DataGridCell">
            <Setter Property="IsReadOnly" Value="{Binding MyIsReadOnly}" />
        </Style>
    </DataGrid.Resources>
    <!-- Column definitions... -->
</DataGrid>

残念ながら、このプロパティは書き込み可能ではないため、これは機能しません。
次に、マウスイベントを傍受して停止しようとする場合がありますが、これにより、ユーザーがF2キーを使用して編集モードに入るのを防ぐことはできません。

PreviewExecutedEvent私がこれを気に入った方法は、DataGridでをリッスンし、条件付きで処理済みとしてフラグを立てることでした。
たとえば、これに似たコードを私のWindowまたはUserControl(または別のより適切な場所)のコンストラクターに追加することによって:

myDataGrid.AddHandler(CommandManager.PreviewExecutedEvent,
    (ExecutedRoutedEventHandler)((sender, args) =>
{
    if (args.Command == DataGrid.BeginEditCommand)
    {
        DataGrid dataGrid = (DataGrid) sender;
        DependencyObject focusScope = FocusManager.GetFocusScope(dataGrid);
        FrameworkElement focusedElement = (FrameworkElement) FocusManager.GetFocusedElement(focusScope);
        MyRowItemModel model = (MyRowItemModel) focusedElement.DataContext;
        if (model.MyIsReadOnly)
        {
            args.Handled = true;
        }
    }
}));

このようにすることで、セルは引き続きフォーカス可能で選択可能になります。
ただし、モデルアイテムで特定の行が許可されていない限り、ユーザーは編集モードに入ることができません。
また、DataGridTemplateColumnを使用することで、パフォーマンスのコストや複雑さに悩まされることはありません。

于 2011-10-02T00:24:40.717 に答える
2

セルに基になるオブジェクト(チェックボックスなど)を設定することで、アプリケーションでこの問題を解決しました-IsHitTestVisible = false; フォーカス可能=false;

var cb = this.dataGrid.Columns[1].GetCellContent(row) as CheckBox;
cb.IsHitTestVisible = false;
cb.Focusable = false;

「行」はDataGridRowです。IsHitTestVisible = falseは、マウスを使用して基になるオブジェクトをクリック/選択/操作できないが、DataGridCellを選択できることを意味します。Focusable = falseは、キーボードで基になるオブジェクトを選択/操作できないことを意味します。これにより、読み取り専用セルのように見えますが、セルを選択することもできます。DataGridがSelectionMode = FullRowに設定されている場合は、「読み取り専用」セルをクリックすると行全体が選択されます。

于 2010-11-17T21:32:51.067 に答える
1

私の解決策は、コンバーターでDataGridTemplateColumnへのバインディングを使用することです。

<UserControl.Resources>
    <c:isReadOnlyConverter x:Key="isRead"/>
</UserControl.Resources>

   <DataGridTemplateColumn x:Name="exampleTemplate" Header="example:" Width="120" IsReadOnly="True">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                            <CheckBox x:Name="exampleCheckBox" VerticalAlignment="Center" IsEnabled="{Binding ElementName=exmpleTemplate, Path=IsReadOnly, Converter={StaticResource isRead}}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

およびコンバーター:

class isReadOnlyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        try
        {
            return !(bool)value;
        }
        catch (Exception)
        {
            return false;
        }
    }
于 2014-11-10T18:47:31.177 に答える
1

これは少し遅いですが、私もこれを調べていました。これらのソリューションはうまく機能しますが、少し違うものが必要でした。次のことを実行しました。これは、私が望んでいたとおりに機能し、質問が何を求めているかを示しています。

基本的に、セルの編集モードに入り、セルを編集できない間、他のすべてのテンプレートとコマンドロジックを同じにできるようにしたかったのです。

このすべての解決策は、DataGridCellスタイルでTextBox.IsReadOnlyプロパティをtrueに設定し、最初のキーダウンイベントを処理することです。

<Style TargetType="DataGridCell">
    <Setter Property="TextBox.IsReadOnly" Value="True"/>
    <EventSetter Event="PreviewKeyDown" Handler="cell_PreviewKeyDown"/>
</Style>

そして、最初の編集を停止するための次のコードビハインド

protected void cell_PreviewKeyDown(object sender, KeyEventArgs e)
{
    DataGridCell cell = sender as DataGridCell;
    if (cell.IsEditing == false && 
        ((Keyboard.Modifiers & ModifierKeys.Control) != ModifierKeys.Control)) //So that Ctrl+C keeps working
    {
        cell.IsEditing = true;
        e.Handled = true;
    }
}

うまくいけば、これがお役に立てば幸いです。

于 2015-03-24T17:06:46.200 に答える
1

@sohumのコメントに基づいて、ここでは、回答としてマークされた応答の簡略化されたバージョンを使用できます。

dataGrid.BeginningEdit += DataGrid_BeginningEdit;

(...)

private static void DataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
    //Actual content of the DataGridCell
    FrameworkElement content = e.Column.GetCellContent(e.Row);
    MyObject myObject = (MyObject)content.DataContext;

    if (!myObject.CanEdit)
    {
        e.Cancel = true;
    }
}

後で添付プロパティの動作として使用できます。

于 2018-08-10T11:45:40.063 に答える
0

DataGridの選択可能な読み取り専用テキストセルを取得する1つの方法は、次のようなテンプレートとスタイルを使用することです。

<DataGrid>
<DataGrid.CellStyle>
    <Style TargetType="{x:Type DataGridCell}">                                        
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <Border Padding="0" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                         <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        <TextBox BorderThickness="0" MouseDoubleClick="DataGrid_TextBox_MouseDoubleClick" IsReadOnly="True" Padding="5" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Text}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</DataGrid.CellStyle>

そしてCSバックエンドの場合:

private void DataGrid_TextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        (sender as TextBox).SelectAll();
    }
于 2013-06-21T10:47:15.643 に答える
0

私の場合、DataGridTextColumnを使用していました。次のように、ContentPresenterのIsEnabledプロパティをStyleに設定しましたが、正常に機能します-

     <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
        <DataGrid.Resources>
            <Style TargetType="{x:Type DataGridCell}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type DataGridCell}">
                            <Grid Background="{TemplateBinding Background}" >
                                <ContentPresenter IsEnabled="{Binding Path=IsEditable}"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.Resources>
        <DataGridTextColumn Header="A" 
                            Binding="{Binding Path=A}"/>
    </DataGrid>
于 2018-09-22T14:01:19.060 に答える
0

これは、より単純なデータテンプレートを使用して行うことができます。

<DataGrid.Resources>
    <DataTemplate x:Key="MyTemplate" DataType="MyRowDataType">
        <TextBox Text="{Binding Value}" IsReadOnly="{Binding IsReadOnly}" />
    </DataTemplate>
</DataGrid.Resources>

..。

<DataGridTemplateColumn CellTemplate="{StaticResource MyTemplate}" />
于 2019-09-13T19:34:23.913 に答える
0

私にとって、最も簡単な解決策は、TextBox内部のスタイルを設定することでしたEditingElementStyle

<DataGridTextColumn Binding="{Binding MyValueProperty}">
    <DataGridTextColumn.EditingElementStyle>
        <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding MyReadonlyProperty}" Value="True">
                    <Setter Property="IsReadOnly" Value="True"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
于 2021-12-10T18:00:54.013 に答える