How to: Create a ListView with Editable Cells

This example shows how to create a ListView control in a GridView view mode that has editable cells.

Example

To edit the cells of a GridViewColumn in a GridView, define a custom control to use as the CellTemplate of the column.

The following example shows a custom control that is named EditBox, which implements two dependency properties, Value and IsEditing. The Value property stores the value of a cell. The IsEditing property specifies whether the cell is currently editable.

    Public Class EditBox
        Inherits Control


...


        Public Shared ReadOnly ValueProperty As DependencyProperty = DependencyProperty.Register("Value", GetType(Object), GetType(EditBox), New FrameworkPropertyMetadata(Nothing))


...


        Public Shared IsEditingProperty As DependencyProperty = DependencyProperty.Register("IsEditing", GetType(Boolean), GetType(EditBox), New FrameworkPropertyMetadata(False))


...


    End Class
public class EditBox : Control
{


...


public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register(
                "Value",
                typeof(object),
                typeof(EditBox),
                new FrameworkPropertyMetadata(null));


...


public static DependencyProperty IsEditingProperty =
        DependencyProperty.Register(
                "IsEditing",
                typeof(bool),
                typeof(EditBox),
                new FrameworkPropertyMetadata(false));


...


}

The following example creates a Style for the EditBox control.

<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>

To create a TextBox control to edit a cell, implement an Adorner. The following example shows the constructor for the EditBoxAdorner.

    Friend NotInheritable Class EditBoxAdorner
        Inherits Adorner


...


        Public Sub New(ByVal adornedElement As UIElement, ByVal adorningElement As UIElement)
            MyBase.New(adornedElement)
            _textBox = TryCast(adorningElement, TextBox)
            Debug.Assert(_textBox IsNot Nothing, "No TextBox!")

            _visualChildren = New VisualCollection(Me)

            BuildTextBox()
        End Sub


...


    End Class
internal sealed class EditBoxAdorner : Adorner
{


...


public EditBoxAdorner(UIElement adornedElement, 
                      UIElement adorningElement): base(adornedElement)
{
    _textBox = adorningElement as TextBox;
    Debug.Assert(_textBox != null, "No TextBox!");

    _visualChildren = new VisualCollection(this);

    BuildTextBox();
}


...


}

To control when the EditBox is editable, use events like MouseUp, MouseLeave, or MouseEnter. The following example shows how the first MouseUp event that is received by an EditBox selects the EditBox, and the second MouseUp event puts the EditBox in editing mode.

    Public Class EditBox
        Inherits Control


...


        Protected Overrides Sub OnMouseUp(ByVal e As MouseButtonEventArgs)
            MyBase.OnMouseUp(e)

            If e.ChangedButton = MouseButton.Right OrElse e.ChangedButton = MouseButton.Middle Then
                Return
            End If

            If Not IsEditing Then
                If (Not e.Handled) AndAlso (_canBeEdit OrElse _isMouseWithinScope) Then
                    IsEditing = True
                End If

                'If the first MouseUp event selects the parent ListViewItem,
                'then the second MouseUp event puts the EditBox in editing 
                'mode
                If IsParentSelected Then
                    _isMouseWithinScope = True
                End If
            End If
        End Sub


...


    End Class
public class EditBox : Control
{


...


protected override void OnMouseUp(MouseButtonEventArgs e)
{
    base.OnMouseUp(e);

    if (e.ChangedButton == MouseButton.Right || 
        e.ChangedButton == MouseButton.Middle)
        return;

    if (!IsEditing)
    {
        if (!e.Handled && (_canBeEdit || _isMouseWithinScope))
        {
            IsEditing = true;
        }

        //If the first MouseUp event selects the parent ListViewItem,
        //then the second MouseUp event puts the EditBox in editing 
        //mode
        if (IsParentSelected)
            _isMouseWithinScope = true;
    }
}


...


}

The following example shows how you use the MouseEnter and MouseLeave events to determine if a cell is eligible for editing.

    Public Class EditBox
        Inherits Control


...


        Protected Overrides Sub OnMouseEnter(ByVal e As MouseEventArgs)
            MyBase.OnMouseEnter(e)
            If (Not IsEditing) AndAlso IsParentSelected Then
                _canBeEdit = True
            End If
        End Sub


...


        Protected Overrides Sub OnMouseLeave(ByVal e As MouseEventArgs)
            MyBase.OnMouseLeave(e)
            _isMouseWithinScope = False
            _canBeEdit = False
        End Sub


...


    End Class
public class EditBox : Control
{


...


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;
}


...


}

To define a GridViewColumn that permits editing, set the CellTemplate property to an EditBox control. The following example specifies the CellTemplate property of a GridViewColumn as an EditBox control.

<GridViewColumn Header="ID" Width="50" >
  <GridViewColumn.CellTemplate>
    <DataTemplate>
      <l:EditBox Height="25" Value="{Binding Path=EmployeeNumber}" />
    </DataTemplate>
  </GridViewColumn.CellTemplate>
</GridViewColumn>

See Also

Reference

Control

ListView

GridView

Concepts

GridView Overview

Other Resources

ListView How-to Topics