How to: Create a ListView with Editable Cells
В этом примере демонстрируется создание элемента управления ListView в режиме представления GridView, который имеет редактируемые ячейки.
Пример
Для редактирования ячеек GridViewColumn в GridView следует определить пользовательский элемент управления для использования в качестве CellTemplate столбца.
В следующем примере показан пользовательский элемент управления с именем EditBox, который реализует два свойства зависимостей — Value и IsEditing.Свойство 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));
...
}
В следующем примере создается Style для элемента управления 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>
Чтобы создать элемент управления 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.Следующий пример показывает, как первое событие MouseUp, получаемое с помощью EditBox, выбирает EditBox, а второе событие 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.В следующем примере свойство CellTemplate из GridViewColumn задается в качестве элемента управления EditBox.
<GridViewColumn Header="ID" Width="50" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<l:EditBox Height="25" Value="{Binding Path=EmployeeNumber}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>