// (c) Copyright Microsoft Corporation. // This source is subject to the Microsoft Public License (Ms-PL). // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // All other rights reserved. using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Media; using System; using System.ComponentModel; using Avalonia.Layout; namespace Avalonia.Controls { /// /// Represents a column that hosts textual content in its cells. /// public class DataGridTextColumn : DataGridBoundColumn { private double? _fontSize; private FontStyle? _fontStyle; private FontWeight? _fontWeight; private IBrush _foreground; /// /// Initializes a new instance of the class. /// public DataGridTextColumn() { BindingTarget = TextBox.TextProperty; } /// /// Identifies the FontFamily dependency property. /// public static readonly StyledProperty FontFamilyProperty = AvaloniaProperty.Register(nameof(FontFamily)); /// /// Gets or sets the font name. /// public string FontFamily { get { return GetValue(FontFamilyProperty); } set { SetValue(FontFamilyProperty, value); } } /// /// Gets or sets the font size. /// // Use DefaultValue here so undo in the Designer will set this to NaN [DefaultValue(double.NaN)] public double FontSize { get { return _fontSize ?? Double.NaN; } set { if (_fontSize != value) { _fontSize = value; NotifyPropertyChanged(nameof(FontSize)); } } } /// /// Gets or sets the font style. /// public FontStyle FontStyle { get { return _fontStyle ?? FontStyle.Normal; } set { if (_fontStyle != value) { _fontStyle = value; NotifyPropertyChanged(nameof(FontStyle)); } } } /// /// Gets or sets the font weight or thickness. /// public FontWeight FontWeight { get { return _fontWeight ?? FontWeight.Normal; } set { if (_fontWeight != value) { _fontWeight = value; NotifyPropertyChanged(nameof(FontWeight)); } } } /// /// Gets or sets a brush that describes the foreground of the column cells. /// public IBrush Foreground { get { return _foreground; } set { if (_foreground != value) { _foreground = value; NotifyPropertyChanged(nameof(Foreground)); } } } /// /// Causes the column cell being edited to revert to the specified value. /// /// The element that the column displays for a cell in editing mode. /// The previous, unedited value in the cell being edited. protected override void CancelCellEdit(IControl editingElement, object uneditedValue) { if (editingElement is TextBox textBox) { string uneditedString = uneditedValue as string; textBox.Text = uneditedString ?? string.Empty; } } /// /// Gets a control that is bound to the column's property value. /// /// The cell that will contain the generated element. /// The data item represented by the row that contains the intended cell. /// A new control that is bound to the column's property value. protected override IControl GenerateEditingElementDirect(DataGridCell cell, object dataItem) { var textBox = new TextBox { VerticalAlignment = VerticalAlignment.Stretch, Background = new SolidColorBrush(Colors.Transparent) }; if (IsSet(FontFamilyProperty)) { textBox.FontFamily = FontFamily; } if (_fontSize.HasValue) { textBox.FontSize = _fontSize.Value; } if (_fontStyle.HasValue) { textBox.FontStyle = _fontStyle.Value; } if (_fontWeight.HasValue) { textBox.FontWeight = _fontWeight.Value; } if (_foreground != null) { textBox.Foreground = _foreground; } return textBox; } /// /// Gets a read-only element that is bound to the column's property value. /// /// The cell that will contain the generated element. /// The data item represented by the row that contains the intended cell. /// A new, read-only element that is bound to the column's property value. protected override IControl GenerateElement(DataGridCell cell, object dataItem) { TextBlock textBlockElement = new TextBlock { Margin = new Thickness(4), VerticalAlignment = VerticalAlignment.Center }; if (IsSet(FontFamilyProperty)) { textBlockElement.FontFamily = FontFamily; } if (_fontSize.HasValue) { textBlockElement.FontSize = _fontSize.Value; } if (_fontStyle.HasValue) { textBlockElement.FontStyle = _fontStyle.Value; } if (_fontWeight.HasValue) { textBlockElement.FontWeight = _fontWeight.Value; } if (_foreground != null) { textBlockElement.Foreground = _foreground; } if (Binding != null) { textBlockElement.Bind(TextBlock.TextProperty, Binding); } return textBlockElement; } /// /// Called when the cell in the column enters editing mode. /// /// The element that the column displays for a cell in editing mode. /// Information about the user gesture that is causing a cell to enter editing mode. /// The unedited value. protected override object PrepareCellForEdit(IControl editingElement, RoutedEventArgs editingEventArgs) { if (editingElement is TextBox textBox) { string uneditedText = textBox.Text ?? String.Empty; int len = uneditedText.Length; if (editingEventArgs is KeyEventArgs keyEventArgs && keyEventArgs.Key == Key.F2) { // Put caret at the end of the text textBox.SelectionStart = len; textBox.SelectionEnd = len; } else { // Select all text textBox.SelectionStart = 0; textBox.SelectionEnd = len; textBox.CaretIndex = len; } return uneditedText; } return string.Empty; } /// /// Called by the DataGrid control when this column asks for its elements to be /// updated, because a property changed. /// protected internal override void RefreshCellContent(IControl element, string propertyName) { if (element == null) { throw new ArgumentNullException("element"); } if(element is TextBox textBox) { if (propertyName == nameof(FontFamily)) { textBox.FontFamily = FontFamily; } else if (propertyName == nameof(FontSize)) { SetTextFontSize(textBox, TextBox.FontSizeProperty); } else if (propertyName == nameof(FontStyle)) { textBox.FontStyle = FontStyle; } else if (propertyName == nameof(FontWeight)) { textBox.FontWeight = FontWeight; } else if (propertyName == nameof(Foreground)) { textBox.Foreground = Foreground; } else { if (FontFamily != null) { textBox.FontFamily = FontFamily; } SetTextFontSize(textBox, TextBox.FontSizeProperty); textBox.FontStyle = FontStyle; textBox.FontWeight = FontWeight; if (Foreground != null) { textBox.Foreground = Foreground; } } } else if (element is TextBlock textBlock) { if (propertyName == nameof(FontFamily)) { textBlock.FontFamily = FontFamily; } else if (propertyName == nameof(FontSize)) { SetTextFontSize(textBlock, TextBlock.FontSizeProperty); } else if (propertyName == nameof(FontStyle)) { textBlock.FontStyle = FontStyle; } else if (propertyName == nameof(FontWeight)) { textBlock.FontWeight = FontWeight; } else if (propertyName == nameof(Foreground)) { textBlock.Foreground = Foreground; } else { if (FontFamily != null) { textBlock.FontFamily = FontFamily; } SetTextFontSize(textBlock, TextBlock.FontSizeProperty); textBlock.FontStyle = FontStyle; textBlock.FontWeight = FontWeight; if (Foreground != null) { textBlock.Foreground = Foreground; } } } else { throw DataGridError.DataGrid.ValueIsNotAnInstanceOfEitherOr("element", typeof(TextBox), typeof(TextBlock)); } } private void SetTextFontSize(AvaloniaObject textElement, AvaloniaProperty fontSizeProperty) { double newFontSize = FontSize; if (double.IsNaN(newFontSize)) { textElement.ClearValue(fontSizeProperty); } else { textElement.SetValue(fontSizeProperty, newFontSize); } } } }