Editing In ListView

ListView does not support editing in V1, but for those who are familiar with File Explorer, editing is quite useful. I will introduce how to make a cell editable in ListView. Furthermore, you will find it is easy to build a custom control.

However, it is just a sample to enable simple editing in ListView. The target scenarios of ListView are displaying items not editing. As for those who have intensive requirements for editing, ListView control may be not a good choice, because we are not sure how far you can go.

Besides, cell keyboard navigation is not enabled.

Idea

To achieve our goal, create a customized control called EditBox for GridViewColumn.CellTemplate.  The EditBox has two modes, one for displaying content in normal way, the other one for displaying content in editable mode. In normal mode, the EditBox displays content in a TextBlock, when in editable mode, it displays content in a TextBox, which lies in the TextBlock's adorner

1. Create a customized Edit Control

To build an EditBox, we need to define its OM(object model) and behaviors first. In our context, the OM can be outlined by the following rules:

  • When the ListViewItem that contains an EditBox is selected, click on the EditBox should switch it into Editing mode.
  • When in editing mode, pressing Enter key or F2 can switch it into Normal mode.
  • When in editing mode, once the TextBox loses its focus, the EditBox should switch to its Normal model.

    Behaviors:

  • In Normal mode, a TextBlock is used to display content;
  • In Editing mode, a TextBox will pop up for editing.     

    Assumptions   

This control is built for a DataTemplate to specify GridViewColumn.CellTemplate. No guarantee that it can work out of GridView.

     Steps

1) Create an EditBox inherited from Control. Since we need a property to store displayed value, we add a dependency property “Value”.

public class EditBox : Control

{

            static EditBox()

            {

          ......

           public static readonly DependencyProperty ValueProperty =

                    DependencyProperty.Register(

                            "Value",

                 typeof(object),

                            typeof(EditBox),

                            new FrameworkPropertyMetadata());

 ......

}

 

2) Add a DependencyProperty to represent the mode: IsEditing. It is of type Boolean, when it is true, EditBox is in Editing mode. We use it to trigger whether to show the TextBox or not.

......

            public static DependencyProperty IsEditingProperty =

                    DependencyProperty.Register(

                            "IsEditing",

                            typeof(bool),

                            typeof(EditBox),

                            new FrameworkPropertyMetadata(false)

                            );

......

 

3)  Style the EditBox.

<Style x:Key="{x:Type l:EditBox}" TargetType="{x:Type l:EditBox}" >

<Setter Property="HorizontalAlignment" Value="Left" />

<Setter Property="Template">

<Setter.Value>

<ControlTemplate TargetType="{x:Type l:EditBox}">

<TextBlock x:Name="PART_TextBlockPart"

Text="{Binding Path=Value, RelativeSource = {RelativeSource TemplatedParent}}">

</TextBlock>

</ControlTemplate>

</Setter.Value>

</Setter>

</Style>

 

4) To enable editing, create EditBoxAdorner to host the TextBox. It needs to do some measuring and arranging work to make TextBox work as expected.

internal sealed class EditBoxAdorner : Adorner

 {

        /// <summary>

        /// Inialize the EditBoxAdorner.

        /// </summary>

        public EditBoxAdorner(UIElement adornedElement, UIElement adorningElement)

            : base(adornedElement)

        {

            _textBox = adorningElement as TextBox;

            Debug.Assert(_textBox != null, "No TextBox!");

            _visualChildren = new VisualCollection(this);

            BuildTextBox();

        }

                        ......

 

     5) To implement all the rules, add some event handling code.(See source code for details)

                  ......

protected override void OnMouseEnter(MouseEventArgs e)

{

base.OnMouseEnter(e);

if (!IsEditing && IsParentSelected)

{

_canBeEdit = true;

}

}

protected override void OnMouseLeave(MouseEventArgs e)

{

base.OnMouseLeave(e);

_isMouseWithinScope = false;

_canBeEdit = false;

}

        ...... 

 

2. Customize CellTemplate

By putting the EditBox in GridViewColumn.CellTemplate, the column can be edited when its ListViewItem is selected and then clicked. For example:

    ......

          <GridViewColumn Header="Month" >

            <GridViewColumn.CellTemplate>

              <DataTemplate>

                <l:EditBox  Value="{Binding Month}"/>

              </DataTemplate>

            </GridViewColumn.CellTemplate>

          </GridViewColumn>

          <GridViewColumn />

         ......

 

Conclusion: To implement editing in GridView, you need to build a customized control that can switch between different modes(Editing and Normal), and then put the control into GridViewColumn.CellTemplate. Here I just demonstrate the idea. You may change it to build a more powerful control that can be used in wider situations.

This sample is based on the February CTP.

Declaimer: This posting is provided "AS IS" with no warranties, and confers no rights.

editing.zip