Frage

Ich verstehe, können Sie das gesamte Datagrid machen oder eine ganze Spalte readyonly (IsReadOnly = true). auf Zellebene jedoch ist diese Eigenschaft nur bereit. Aber ich diesen Grad an Granularität brauchen. Es gibt Blog über IsReadOnly auf eine Zeile hinzufügen, indem Sie den Quellcode in alten Zeiten zu ändern, wenn Datagrid war public domain, aber jetzt habe ich Quellcode nicht für Datagrid hat. Was ist Abhilfe?

Erstellen deaktiviert Zelle (IsEnabled = false) trifft fast mein Bedürfnis. Aber das Problem ist, dass man nicht einmal die deaktivierte Zelle klicken Sie auf die Zeile auszuwählen (I Vollzeilenauswahlmodus haben).

EDIT: Da niemand auf diese Frage geantwortet hat, so dass ich denke, es ist nicht leicht zu beheben. Hier ist eine mögliche Abhilfe: Stellen Sie die Zelle nicht bearbeitet werden. Das einzige Problem ist, dass die Zelle klicken nicht die Zeile auswählt. Ich habe gerade bemerkt, dass MouseDown- oder MouseUp-Ereignis des Datagrid immer noch ausgelöst, wenn die behinderte Zelle angeklickt wird. In diesen Event-Handler, wenn ich die Zeile darauf geklickt herausfinden konnte, konnte ich die Zeile programmatisch auszuwählen. Allerdings konnte ich nicht herausfinden, wie die zugrunde liegende Reihe von DataGrid.InputHitTest zu finden. Kann jemand mir bitte etwas Tip geben?

War es hilfreich?

Lösung

Ich habe das gleiche Problem festgestellt, sollte die Zelle in einigen Zeilen nur gelesen werden, aber nicht in den anderen. Hier ist eine Umgehungslösung:

Die Idee ist, um dynamisch die CellEditingTemplate zwischen zwei Vorlagen zu wechseln, eine die gleiche wie die in der CellTemplate, das andere für die Bearbeitung ist. Dies macht den Bearbeitungsmodus wirkt genau die gleiche wie die Nicht-Bearbeitung Zelle, obwohl es im Bearbeitungsmodus befindet.

Im Folgenden ist ein Beispielcode, dies zu tun, bemerkt, dass dieser Ansatz DataGridTemplateColumn erfordert:

Zunächst definiert zwei Vorlagen für schreibgeschützte und Bearbeiten Zellen:

<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>

definieren dann eine Datenvorlage mit zusätzlicher ContentPresenter Schicht und die Verwendung Trigger ContentTemplate des ContentPresenter zu schalten, so dass die obigen zwei Vorlagen dynamisch durch den IsEditable geschaltet werden können Bindung:

<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

Andere Tipps

Nach langem Suchen und Experimentieren mit IsTabStop = False und Fokussierbare = False funktioniert am besten für mich.

<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>

Es ist eine Eigenschaft auf DataGridCell.IsReadOnly, dass Sie vielleicht denken Sie an,
binden z.B. mithilfe von XAML wie folgt aus:

<!-- 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>

Unfortunantly Das wird nicht funktionieren, weil diese Eigenschaft ist nicht beschreibbar.
Weiter Sie abfangen und Stop-Mausereignisse versuchen könnten, aber das wird den Benutzer Eingabe Bearbeitungsmodus mit der Taste F2 nicht verhindern.

So wie ich diese sloved war, indem Sie auf das Datagrid für die PreviewExecutedEvent hören und dann bedingt nachlass als behandelt.
Z.B. durch Hinzufügen von Code ähnlich wie diese an den Konstruktor von meinem Fenster oder Usercontrol (oder einem anderen geeigneteren Ort):

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;
        }
    }
}));

Mit dem es so tun sind die Zellen noch fokussierbar und wählbar.
Aber der Benutzer in der Lage, nicht EditMode es sei denn, Ihr Modell Artikel es für die gegebene Zeile ermöglichen.
Und Sie werden nicht die Leistungskosten oder Komplexität leiden durch die Verwendung von Datagridtemplatecolumn.

habe ich dieses Problem in meiner Anwendung gelöst, indem die zugrunde liegende Aufgabe in der Zelle einstellen (zB CheckBox.) - IsHitTestVisible = false; Fokussierbare = false;

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

"Reihe" ist ein DataGridRow. IsHitTestVisible = false, bedeutet, dass Sie kippen klicken / select / das darunter liegende Objekt per Maus manipulieren, aber Sie können immer noch die Datagridcell wählen. Fokussierbare = false, bedeutet, dass Sie nicht wählen können / manipulieren, um das darunter liegende Objekt mit der Tastatur. Dies gibt die Illusion einer Zelle Readonly, aber Sie können immer noch die Zelle auswählen und ich bin sicher, wenn das Datagrid einzurichten ist Selection = FullRow dann auf die Schaltfläche „read only“ Zelle wird die gesamte wählen Zeile.

Meine Lösung ist auf die Datagridtemplatecolumn mit Konverter zu verwenden, zu binden.

<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>

und der Wandler:

class isReadOnlyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        try
        {
            return !(bool)value;
        }
        catch (Exception)
        {
            return false;
        }
    }

Basierend auf @sohum Kommentar, hier können Sie vereinfachte Version der Antwort verwenden als Antwort markiert.

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;
    }
}

Sie können es später als angebaute Property Verhalten.

Eine Möglichkeit, wählbar zu bekommen, Nur-Lese-Textzellen für Datagrid ist Vorlage und Stil wie folgt zu verwenden:

<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>

Und für CS-Backend:

private void DataGrid_TextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        (sender as TextBox).SelectAll();
    }

Das ist ein bisschen spät, aber ich war auch in diesem suchen, diese Lösungen funktionieren gut, aber ich brauchte etwas ein wenig anders, habe ich die folgenden und es funktioniert genau wie ich wollte, und was die Frage sucht.

ich im Wesentlichen wollte ich in der Lage sein, den Bearbeitungsmodus für die Zelle zu betreten und hat das alles andere Vorlagen und Befehlslogik der gleichen, während nicht zu bearbeiten in der Lage, die Zelle.

Die Lösung für all dies ist die TextBox.IsReadOnly Eigenschaft auf true in dem Datagridcell Stil zu setzen und das anfängliche keydown Ereignis

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

und der folgende Code hinter der anfänglichen bearbeiten zu stoppen

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;
    }
}

Hoffentlich ist das hilfreich.

In meinem Fall war ich mit Datagridtextcolumn. Ich habe die IsEnabled Eigenschaft auf Content in der Art wie folgt und es funktioniert gut -

     <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>

Sie können dies tun, mit einer einfacheren Datenvorlage.

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

...

<DataGridTemplateColumn CellTemplate="{StaticResource MyTemplate}" />
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top