2017-02-25 81 views
0

我已经创建了多行和多列的数据网格。其中一列是用户可以更改的字段大小列表。如何根据以前的值验证数据网格值

我正在检查旧值的新值,如果新值小于旧值我告诉用户这是无效的,然后我想把旧值重新设置,并重新设置为重点细胞。

我有这行我LostFocus事件:

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

当我点击单元格中,LostFocus事件被称为和工作正常。但是,当我尝试重新调整单元格时,出现一条错误消息:

“无法将类型为”System.Windows.Controls.TextBlock“的对象转换为键入”System.Windows.Controls.TextBox“。

如何解决此问题?

这里是我的XAML代码:

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

这里是我的C#代码:

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

我正在上的错误这行'Int32 intCurrSize = Convert.ToInt32(strFieldInfoOrig [dtGrid.Items.IndexOf(dtGrid.CurrentItem),1]);''它防止代码编译 - 你确定这是正确的吗? – Bassie

+0

#Bassue - 这对我有用。在第一次运行时,我输入一个较小的数字,然后进入if语句和错误消息。 – Cass

回答

0

发生这种情况,因为DataGridTextColumn展示在正常模式下的TextBlockTextBox同时编辑。所以,当这个单元失去焦点时,DataGridTextColumn以正常模式返回,所以其内容将是TextBlock而不是TextBox,因此它显示异常。

因此,尽量投入TextBlock而不是TextBox

0

您可以处理CellEditEnding事件。

背后

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

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

     ... 

    </DataGrid.Columns> 

    ... 

</DataGrid> 

代码保持在编辑模式下的单元格。

+0

#bab7lon - 在字符串上失败oldValue = e.Row.DataContext.GetType()。GetProperty(“Size”) .GetValue(e.Row.DataContext).ToString();它看起来.GetProperty(“大小”)返回null,我认为 – Cass

+0

@Cass你怎么填写'数据网格'加载''?你是否将'ItemsSource'绑定到一个集合,使用'DataTable',...? – bab7lon

+0

是的我加载一个数据表的值,然后绑定到datagrid.ItemsSource,dtGrid.ItemsSource = dtGridData.DefaultView;我能够解决这个错误,DataRowView drvRowView =(DataRowView)e.Row.DataContext; string oldValue = drvRowView.Row.ItemArray [1] .ToString(); – Cass

0

您正试图将TextBlock投射到TextBox,这显然不起作用。但如果你只是一味的总是转换为TextBlock这样的:

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

...这将不能工作。这是因为单元的Content可能是TextBox a TextBlock,这取决于单元当前是否处于编辑模式。

尽你所能的就是使用as运营商尝试投射到一个TextBox如果转换失败,你再铸造Content属性设置为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

你试过这个吗? – bab7lon

+0

#bab7lon - 我正在尝试它,对于延迟抱歉,我的电脑崩溃,我现在刚刚恢复 – Cass