Как проверить значение ячейки данных на основе предыдущего значения
Я создал сетку данных из нескольких строк и столбцов. Один из столбцов представляет собой список размеров полей, которые пользователь может изменить.
Я проверяю новое значение по сравнению со старым значением, и если новое значение меньше, чем старое значение, я говорю пользователю, что оно недопустимо, и затем я хочу вернуть старое значение обратно и вернуть фокус в эту ячейку.
У меня есть эта строка в моем 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();
}
}
}
3 ответа
Вы можете обработать событие CellEditEnding.
<DataGrid AutoGenerateColumns="False"
CellEditEnding="DataGrid_CellEditEnding"
...
>
<DataGrid.Columns>
<DataGridTextColumn Header="Size" Binding="{Binding Size, Mode=TwoWay}" .../>
...
</DataGrid.Columns>
...
</DataGrid>
Код позади
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
держит ячейку в режиме редактирования.
Вы пытаетесь разыграть TextBlock
к TextBox
и это, очевидно, не сработает. Но если вы просто пытаетесь всегда бросать TextBlock
как это:
System.Windows.Controls.TextBlock tbNewSize = (System.Windows.Controls.TextBlock)dtgCell.Content;
... это тоже не сработает. Это потому что Content
клетки могут быть TextBox
или 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();
}
}
}
Это происходит потому, что DataGridTextColumn
показывает TextBlock
в обычном режиме и TextBox
во время редактирования. Итак, когда эта клетка теряет фокус, DataGridTextColumn
возвращается в нормальном режиме, поэтому его содержимое будет TextBlock
и не TextBox
и, следовательно, это показывает исключение.
Итак, попробуйте бросить в TextBlock
и не TextBox
,