[WPF] 自建DataGrid Column

在WPF 的DataGrid 中, 若需要自設DataGridColumn, 可以利用XAML DataGridTemplateColumn. 然而若遇到AutoGenerateColumn為true 或須要增加其re-usability 時, 自建user control 反而比較化算. 

在這裡, 會建立兩個DataGird column來分別存取數字和日期. 

建立DataGrid column 時, 只須要建立一個class 並inherit DataGridBoundColumn 或其sub class 便可. 之後再implement method 分別建立View 及Edit 時的DataTemplate 便可.

DateGridDateTimeColumn.cs

public class DataGridDateTimeColumn : DataGridBoundColumn
    {
        protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
        {
            return GenerateDatePicker(dataItem);
        }

        protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
        {
            return GenerateTextBlock(dataItem);
        }

        private DatePicker GenerateDatePicker(object source)
        {
            DatePicker result = new DatePicker()
            {
                Margin = new Thickness() { Bottom = 0, Left = 0, Right = 0, Top = 0 },
                Padding = new Thickness() { Bottom = -2, Left = -2, Right = -2, Top = -2 }
            };
            Binding baseBinding = this.Binding as Binding;
            Binding binding = new Binding()
            {
                Path = baseBinding.Path,
                Source = source,
                Mode = BindingMode.TwoWay,
                StringFormat = Properties.Settings.Default.DisplayDateFormat
            };
            result.SetBinding(DatePicker.SelectedDateProperty, binding);
            return result;
        }

        private TextBlock GenerateTextBlock(object source)
        {
            TextBlock result = new TextBlock()
            {
                Margin = new Thickness() { Bottom = 0, Left = 0, Right = 0, Top = 0 },
                TextAlignment = TextAlignment.Left,
                VerticalAlignment = VerticalAlignment.Top
            };
            Binding baseBinding = this.Binding as Binding;
            Binding binding = new Binding()
            {
                Path = baseBinding.Path,
                Source = source,
                Mode = BindingMode.TwoWay,
                StringFormat = Properties.Settings.Default.DisplayDateFormat
            };
            result.SetBinding(TextBlock.TextProperty, binding);
            return result;
        }
    }

DataGridNumericColumn.cs

public class DataGridNumericColumn : DataGridTextColumn
    {
        protected override object PrepareCellForEdit(System.Windows.FrameworkElement editingElement, System.Windows.RoutedEventArgs editingEventArgs)
        {
            TextBox edit = editingElement as TextBox;
            edit.PreviewTextInput += OnPreviewTextInput;

            return base.PrepareCellForEdit(editingElement, editingEventArgs);
        }

        private void OnPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
        {
            e.Handled = (!IsDataValid(e.Text));
        }

        private void OnPaste(object sender, DataObjectPastingEventArgs e)
        {
            var data = e.SourceDataObject.GetData(DataFormats.Text);
            if (!IsDataValid(data)) e.CancelCommand();
        }

        private bool IsDataValid(object data)
        {
            return ((string)data).IsNumeric();
        }
    }

叫用時, 只須設定好xml namesapace 後, 像平時用user control 般便可. 例如:

<DataGrid.Columns>
                <local:DataGridNumericColumn Header="Number" Binding="{Binding NumericProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <local:DataGridDateTimeColumn Header="Date" Binding="{Binding DateTimeProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataGrid.Columns>

 

About C.H. Ling 260 Articles
a .net / Java developer from Hong Kong and currently located in United Kingdom. Thanks for Google because it solve many technical problems so I build this blog as return. Besides coding and trying advance technology, hiking and traveling is other favorite to me, so I will write down something what I see and what I feel during it. Happy reading!!!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


This site uses Akismet to reduce spam. Learn how your comment data is processed.