How to: Create a ListView with Editable Cells
この例では、編集可能なセルを含む ListView コントロールを GridView 表示モードで作成する方法を示します。
使用例
GridView で GridViewColumn のセルを編集するには、列の CellTemplate として使用するカスタム コントロールを定義します。
次の例では、EditBox という名前のカスタム コントロールを示します。このコントロールは、Value と IsEditing という 2 つの依存関係プロパティを実装しています。Value プロパティは、セルの値を格納します。IsEditing プロパティは、セルが現在編集可能かどうかを指定します。
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));
...
}
次の例では、EditBox コントロールの Style を作成します。
<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>
セルを編集するための TextBox コントロールを作成するには、Adorner を実装します。次の例では、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();
}
...
}
EditBox が編集可能になったかどうかを制御するには、MouseUp、MouseLeave、MouseEnter などのイベントを使用します。次の例では、EditBox が受け取る最初の MouseUp イベントで EditBox を選択し、2 番目の MouseUp イベントで EditBox を編集モードにする方法を示します。
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;
}
}
...
}
次の例では、MouseEnter イベントと MouseLeave イベントを使用して、セルが編集対象として適切かどうかを判定する方法を示します。
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;
}
...
}
編集が可能な GridViewColumn を定義するには、CellTemplate プロパティに EditBox コントロールを設定します。次の例では、GridViewColumn の CellTemplate プロパティを EditBox コントロールとして指定しています。
<GridViewColumn Header="ID" Width="50" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<l:EditBox Height="25" Value="{Binding Path=EmployeeNumber}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>