2017-02-25 4 views
0

Ich habe ein Datagrid aus mehreren Zeilen und Spalten erstellt. Eine der Spalten ist eine Liste von Feldgrößen, die der Benutzer ändern kann.So validieren Sie den Wert von datagridcell basierend auf dem vorherigen Wert

Ich überprüfe den neuen Wert gegen den alten Wert und wenn der neue Wert kleiner ist als der alte Wert, sage ich dem Benutzer, das ist nicht gültig und dann möchte ich den alten Wert zurück setzen und den Fokus darauf zurücksetzen Zelle.

Ich habe diese Zeile in meinem LostFocus Veranstaltung:

System.Windows.Controls.TextBox tbNewSize = 
    (System.Windows.Controls.TextBox)dtgCell.Content; 

Wenn ich auf die Zelle klicken, wird das LostFocus Ereignis aufgerufen und funktioniert einwandfrei. Jedoch wenn ich versuche, an die Zelle refokussieren bekomme ich eine Fehlermeldung,

„Kann nicht das Objekt des Typs‚System.Windows.Controls.TextBlock‘werfen‚System.Windows.Controls.TextBox‘zu geben.“

Wie behebe ich dieses Problem?

Hier ist meine XAML-Code:

<DataGrid HeadersVisibility="Column" Name="dtGrid" Loaded="GridLoaded" AutoGenerateColumns="False" IsReadOnly="False" VirtualizingPanel.IsVirtualizing="False" Height="365" Width="530" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="54,74,0,0" BorderThickness="1,1,0,1" BorderBrush="Black"> 
<DataGrid.Columns> 
    <DataGridTextColumn Header="Field" Binding="{Binding Field, Mode=TwoWay}" Width="209" IsReadOnly="True" /> 
    <DataGridTextColumn Header="Size" Binding="{Binding Size, Mode=TwoWay}" Width="89"/> 
    <DataGridCheckBoxColumn Header="Right Justify" Binding="{Binding RightJustify, Mode=TwoWay}" Width="55" /> 
    <DataGridCheckBoxColumn Header="Left Justify" Binding="{Binding LeftJustify, Mode=TwoWay}" Width="55" /> 
    <DataGridCheckBoxColumn Header="Left Zero Fill" Binding="{Binding LeftZeroFill, Mode=TwoWay}" Width="55" /> 
    <DataGridCheckBoxColumn Header="Right Zero Fill" Binding="{Binding RightZeroFill, Mode=TwoWay}" Width="65" /> 
</DataGrid.Columns> 
<DataGrid.ColumnHeaderStyle> 
    <Style TargetType="DataGridColumnHeader"> 
     <Setter Property="ContentTemplate"> 
      <Setter.Value> 
       <DataTemplate> 
        <TextBlock TextWrapping="Wrap" Text="{Binding}"></TextBlock> 
       </DataTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</DataGrid.ColumnHeaderStyle> 
<DataGrid.Resources> 
    <Style TargetType="{x:Type DataGridCell}"> 
     <Style.Triggers> 
      <Trigger Property="DataGridCell.IsSelected" Value="True"> 
       <Setter Property="Background" Value="#FF9DF3D6" /> 
       <Setter Property="Foreground" Value="#000000" /> 
      </Trigger> 
     </Style.Triggers> 
     <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown" /> 
     <EventSetter Event="LostFocus" Handler="DataGridCell_OnCellLostFocus" /> 
    </Style> 
</DataGrid.Resources> 

Hier ist mein C# -Code:

private void DataGridCell_OnCellLostFocus(object sender, RoutedEventArgs e) 
{ 
    System.Windows.Controls.DataGridCell dtgCell = (System.Windows.Controls.DataGridCell)sender; 

    if (dtgCell.Column.Header.ToString() == "Size") 
    { 
     System.Windows.Controls.TextBox tbNewSize = (System.Windows.Controls.TextBox)dtgCell.Content; 
     Int32 intNewSize = Convert.ToInt32(tbNewSize.Text); 
     Int32 intCurrSize = Convert.ToInt32(strFieldInfoOrig[dtGrid.Items.IndexOf(dtGrid.CurrentItem), 1]); 

     if (intNewSize < intCurrSize) 
     { 
      string strMsg; 

      strMsg = "New size, " + intNewSize.ToString() + " is smaller then the original size, " + intCurrSize.ToString(); 
      strMsg += Environment.NewLine; 
      strMsg += "Due to potential data loss, this is not allowed."; 
      System.Windows.MessageBox.Show(strMsg); 
      //dtgCell.Content = intCurrSize.ToString(); 
      dtgCell.Focus(); 
     } 
    } 
} 
+0

ich eine Störung erhalte auf Diese Zeile 'Int32 intCurrSize = Convert.ToInt32 (strFieldInfoOrig [dtGrid.Items.IndexOf (dtGrid.CurrentItem), 1]);' verhindert die Kompilierung des Codes - sind Sie sicher, dass das korrekt ist? – Bassie

+0

#Bassue - Das funktioniert für mich. Beim ersten Durchlauf gebe ich eine kleinere Zahl ein und ich komme in die if-Anweisung und die Fehlermeldung. – Cass

Antwort

0

Dies geschieht, weil DataGridTextColumn zeigt ein TextBlock im normalen Modus und TextBox während der Bearbeitung. Wenn also diese Zelle den Fokus verliert, kehrt DataGridTextColumn im normalen Modus zurück, so dass ihr Inhalt ein TextBlock und nicht TextBox ist und daher eine Ausnahme anzeigt.

Also, versuchen Sie in TextBlock und nicht TextBox zu werfen.

0

Sie konnten die CellEditEnding Ereignis behandeln.

<DataGrid AutoGenerateColumns="False" 
      CellEditEnding="DataGrid_CellEditEnding" 
      ... 
      > 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Size" Binding="{Binding Size, Mode=TwoWay}" .../> 

     ... 

    </DataGrid.Columns> 

    ... 

</DataGrid> 

-Code hinter

private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) 
{ 
    DataGrid datagrid = sender as DataGrid; 
    if (e.EditAction == DataGridEditAction.Commit) 
    { 
     if (e.Column is DataGridBoundColumn) 
     { 
      DataGridBoundColumn column = (DataGridBoundColumn)e.Column; 
      if (column.Header.ToString() == "Size") 
      { 
       string oldValue = e.Row.DataContext.GetType().GetProperty("Size") 
            .GetValue(e.Row.DataContext).ToString(); 
       TextBox element = e.EditingElement as TextBox; 
       string newValue = element.Text; 
       int oldSize = int.Parse(oldValue); 
       int newSize = int.Parse(newValue); 
       if (newSize < oldSize) 
       { 
        string strMsg = "New size, " + newValue + ", is smaller then the original size, " 
            + oldValue + ".\nDue to potential data loss, this is not allowed."; 
        MessageBox.Show(strMsg); 
        element.Text = oldValue; 
        e.Cancel = true; 
       } 
      } 
     } 
    } 
} 

e.Cancel = true Einstellung hält die Zelle im Bearbeitungsmodus.

+0

# bab7lon - es scheitert an der Zeichenfolge oldValue = e.Row.DataContext.GetType(). GetProperty ("Größe") . GetValue (e.Row.DataContext) .ToString(); Es scheint, dass die .GetProperty ("Size") Null zurückgibt, ich denke – Cass

+0

@Cass Wie fülle ich das 'DataGrid' auf' Loaded'? Binden Sie die 'ItemsSource' an eine Sammlung mit einer' DataTable', ...? – bab7lon

+0

Ja Ich lade eine Datentabelle mit den Werten und binde dann das an die Datagrid.ItemsSource, dtGrid.ItemsSource = dtGridData.DefaultView; Ich bin in der Lage, um den Fehler dabei zu umgehen, DataRowView drvRowView = (DataRowView) e.Row.DataContext; Zeichenfolge oldValue = drvRowView.Row.ItemArray [1] .ToString(); – Cass

0

Sie versuchen, eine TextBlock in eine TextBox zu werfen und dies wird offensichtlich nicht funktionieren. Aber wenn man einfach versuchen, immer zu gieße einem TextBlock wie folgt aus:

System.Windows.Controls.TextBlock tbNewSize = (System.Windows.Controls.TextBlock)dtgCell.Content; 

... das wird auch nicht funktionieren. Dies liegt daran, die Content der Zelle ein TextBoxoder ein TextBlock je nach sein kann, ob die Zelle zur Zeit im Bearbeitungsmodus oder nicht.

Was man konnte, ist die as Betreiber zu verwenden versuchen, zu einem TextBox zu werfen und wenn die Umwandlung fehlschlägt Sie werfen dann die Content Immobilie an einen TextBlock:

private void DataGridCell_OnCellLostFocus(object sender, RoutedEventArgs e) 
{ 
    System.Windows.Controls.DataGridCell dtgCell = (System.Windows.Controls.DataGridCell)sender; 
    if (dtgCell.Column.Header.ToString() == "Size") 
    { 
     string text = null; 
     System.Windows.Controls.TextBox tbNewSize = dtgCell.Content as System.Windows.Controls.TextBox; 
     if (tbNewSize != null) 
     { 
      text = tbNewSize.Text; 
     } 
     else 
     { 
      System.Windows.Controls.TextBlock tb = dtgCell.Content as System.Windows.Controls.TextBlock; 
      if (tb != null) 
       text = tb.Text; 
     } 
     Int32 intNewSize = Convert.ToInt32(text); 
     Int32 intCurrSize = Convert.ToInt32(strFieldInfoOrig[dtGrid.Items.IndexOf(dtGrid.CurrentItem), 1]); 

     if (intNewSize < intCurrSize) 
     { 
      string strMsg; 

      strMsg = "New size, " + intNewSize.ToString() + " is smaller then the original size, " + intCurrSize.ToString(); 
      strMsg += Environment.NewLine; 
      strMsg += "Due to potential data loss, this is not allowed."; 
      System.Windows.MessageBox.Show(strMsg); 
      //dtgCell.Content = intCurrSize.ToString(); 
      dtgCell.Focus(); 
     } 
    } 
} 
+0

Haben Sie das versucht? – bab7lon

+0

# bab7lon - Ich versuche es jetzt, Entschuldigung für die Verzögerung, mein Computer ist abgestürzt und ich bin gerade wieder gesund – Cass

Verwandte Themen