我有一个 wpf 数据网格,每行有一些非常大的行和一些可编辑的单元格。
我想在用户导航到它时使单元格可编辑,而不是使用单击或 dbl 单击。类似 Excel 的东西。
1-Datagrid可以吗?如何执行?
2-如何让用户使用箭头键提交单元格更改?
更新:
<DataGrid x:Name="DataGridDatosPlanillla" Margin="5" Grid.Row="1" Width="Auto" Height="Auto" Grid.ColumnSpan="2" CanUserReorderColumns="False" AutoGenerateColumns="False"
ItemsSource="{Binding Path=PlanillaDetalle}" SelectionChanged="DataGridDatosPlanillla_SelectionChanged"
Style="{StaticResource ResourceKey=Datagridstyle}" KeyboardNavigation.AcceptsReturn="True" KeyboardNavigation.DirectionalNavigation="Contained" BeginningEdit="DataGridDatosPlanillla_BeginningEdit" CurrentCellChanged="DataGridDatosPlanillla_CurrentCellChanged" FocusableChanged="DataGridDatosPlanillla_FocusableChanged">
<DataGrid.Columns>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Path=Orden}" ClipboardContentBinding="{x:Null}" Header="{x:Static resources:Labels.GENERAL_IdFila}" CanUserSort="False"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Path=Merlin_Contratos.StrNombreUsuario}" ClipboardContentBinding="{x:Null}" Header="{x:Static resources:Labels.ACOPIO_NombreTercero}" CanUserSort="False"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Path=Merlin_ConceptosFacturacion.StrDescripcionConcepto}" ClipboardContentBinding="{x:Null}" Header="{x:Static resources:Labels.ITEMS_Nombre}" CanUserSort="False"/>
<DataGridTemplateColumn ClipboardContentBinding="{x:Null}" Header="{x:Static resources:Labels.ACOPIO_Recogida1}" CanUserSort="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<controls:NumericTextBox DecimalPlaces="{Binding Path=Merlin_ConceptosFacturacion.IntPlazasDecimales}" Text="{Binding Path=QProductor1}" BorderThickness="0"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn ClipboardContentBinding="{x:Null}" Header="{x:Static resources:Labels.ACOPIO_CantidadDescontada}" CanUserSort="False" CanUserResize="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<controls:NumericTextBox DecimalPlaces="{Binding Path=Merlin_ConceptosFacturacion.IntPlazasDecimales}" Text="{Binding Path=QDescontada}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn IsReadOnly="True" ClipboardContentBinding="{x:Null}" Header="{x:Static resources:Labels.ACOPIO_TotalRecibido}" CanUserSort="False" CanUserResize="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<controls:NumericTextBox DecimalPlaces="{Binding Path=Merlin_ConceptosFacturacion.IntPlazasDecimales}" Text="{Binding Path=QRecibida}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
这是我的自定义控件
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace Recursos.Controls
{
public class CustomFormat : IFormatProvider, ICustomFormatter
{
int DecimalPlaces = 0;
public CustomFormat(int decimalPlaces)
{
DecimalPlaces = decimalPlaces;
}
public object GetFormat(Type FormatType)
{
if (FormatType == typeof(ICustomFormatter))
return this;
else
return null;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (!this.Equals(formatProvider))
return null;
if (string.IsNullOrEmpty(format))
format = "N";
string numericString = arg.ToString();
return numericString;
}
}
public class NumericTextBox : TextBox
{
#region Formato
private string previousText = "";
private bool ApplyingFormat = false;
private CultureInfo _CI = new CultureInfo(CultureInfo.CurrentCulture.LCID,true);
public CultureInfo CI
{
get { return _CI; }
set { _CI = value; }
}
public static readonly DependencyProperty DecimlaPlacesProperty = DependencyProperty.Register(
"DecimalPlaces",
typeof(int),
typeof(NumericTextBox),
new FrameworkPropertyMetadata(0,
FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(OnDecimalPlacesChanged)
)
);
private static void OnDecimalPlacesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
/// <summary>
/// Numero de plazas decimales
/// </summary>
public int DecimalPlaces
{
get { return (int)GetValue(DecimlaPlacesProperty); }
set { SetValue(DecimlaPlacesProperty,value); _CI.NumberFormat.NumberDecimalDigits = value; }
}
public Decimal DecimalValue = 0;
private string _DecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
public string DecimalSeparator
{
get { return _DecimalSeparator; }
set { _DecimalSeparator = value; _CI.NumberFormat.NumberDecimalSeparator = _DecimalSeparator; }
}
//public string DecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
#endregion
public NumericTextBox()
{
HorizontalContentAlignment = HorizontalAlignment.Right;
DataObject.AddPastingHandler(this, OnPaste);
}
private void OnPaste(object sender, DataObjectPastingEventArgs dataObjectPastingEventArgs)
{
var isText = dataObjectPastingEventArgs.SourceDataObject.GetDataPresent(System.Windows.DataFormats.Text, true);
if (isText)
{
var text = dataObjectPastingEventArgs.SourceDataObject.GetData(DataFormats.Text) as string;
if (IsTextValid(text))
{
return;
}
}
dataObjectPastingEventArgs.CancelCommand();
}
private bool IsTextValid(string enteredText)
{
// If keyboard insert key is in toggled mode, and the actual insert point is Decimalseparator, we must avoid to overwrite it
if (SelectionStart == this.Text.IndexOf(DecimalSeparator)
& System.Windows.Input.Keyboard.GetKeyStates(System.Windows.Input.Key.Insert) == System.Windows.Input.KeyStates.Toggled)
{
SelectionStart += 1;
}
if (!enteredText.All(c => Char.IsNumber(c) || c == DecimalSeparator.ToCharArray()[0] || c == '-'))
{
return false;
}
//We only validation against unselected text since the selected text will be replaced by the entered text
var unselectedText = this.Text.Remove(SelectionStart, SelectionLength);
if ( enteredText == DecimalSeparator && unselectedText.Contains(DecimalSeparator))
{
// Before return false, must move cursor beside Decimal separator
SelectionStart = this.Text.IndexOf(DecimalSeparator) + 1;
return false;
}
if (enteredText == "-" && unselectedText.Length > 0)
{
return false;
}
return true;
}
private bool ApplyFormat(TextChangedEventArgs e)
{
if (!ApplyingFormat)
{
ApplyingFormat = true;
int SelectionStartActual = SelectionStart;
string FinallText = this.Text;
if (!FinallText.Contains(DecimalSeparator) & DecimalPlaces > 0)
{
FinallText = String.Format("{0}{1}{2}", this.Text, DecimalSeparator, new string('0', DecimalPlaces));
}
bool state = Decimal.TryParse(FinallText, NumberStyles.AllowCurrencySymbol | NumberStyles.AllowDecimalPoint | NumberStyles.AllowTrailingSign, _CI, out DecimalValue);
DecimalValue = Math.Round(DecimalValue, DecimalPlaces);
if (DecimalValue == 0)
{
FinallText = "";
}
else
{
if (FinallText != DecimalValue.ToString(_CI))
{
FinallText = DecimalValue.ToString(_CI);
}
}
if (FinallText != this.Text)
{
this.Text = FinallText;
SelectionStart = SelectionStartActual;
}
previousText = this.Text;
ApplyingFormat = false;
return state;
}
else
{
return true;
}
}
protected override void OnTextChanged(TextChangedEventArgs e)
{
e.Handled = !ApplyFormat(e);
base.OnTextChanged(e);
}
protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
{
e.Handled = !IsTextValid(e.Text);
base.OnPreviewTextInput(e);
}
}
}