I'm working on a making a WPF Editable listview for my application and it's going great so far (except for that final issue right
). Code included at the end.
I'm having difficulty getting the tab sequence to work properly. All the edit controls show up properly in the listview - and edit the data they are bound to. I can tab between columns that are within the same row, but I can't tab to the next row - it goes to the next control instead of the next row.
Does anyone know how to solve this?
Thanks
----------------------------
![[wink] [wink] [wink]](/data/assets/smilies/wink.gif)
I'm having difficulty getting the tab sequence to work properly. All the edit controls show up properly in the listview - and edit the data they are bound to. I can tab between columns that are within the same row, but I can't tab to the next row - it goes to the next control instead of the next row.
Does anyone know how to solve this?
Thanks
----------------------------
Code:
<Window x:Class="Window1"
xmlns="[URL unfurl="true"]http://schemas.microsoft.com/winfx/2006/xaml/presentation"[/URL]
xmlns:x="[URL unfurl="true"]http://schemas.microsoft.com/winfx/2006/xaml"[/URL]
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
Title="Window1" Height="386" Width="461" Name="Window1">
<Window.Resources>
<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">
<GradientStop Color="#ABADB3" Offset="0.05"/>
<GradientStop Color="#E2E3EA" Offset="0.07"/>
<GradientStop Color="#E3E9EF" Offset="1"/>
</LinearGradientBrush>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
<Style TargetType="{x:Type TextBlock}" x:Key="GridBlockStyle">
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}" Value="True">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}" Value="False">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type FrameworkElement}" x:Key="GridEditStyle">
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type Label}" x:Key="GridBlockStylePM">
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}" Value="True">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}" Value="False">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsMarkup}" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding PriceMarkup}" TextAlignment="Right" />
<TextBlock Grid.Column="1">%</TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsMarkup}" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0">$</TextBlock>
<TextBlock Grid.Column="1" Text="{Binding PriceMarkup}" TextAlignment="Right" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type TextBox}" x:Key="GridEditStylePM">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Cursor" Value="IBeam" />
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMarkup}" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Microsoft_Windows_Themes:ListBoxChrome SnapsToDevicePixels="true" x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost" />
<TextBlock Grid.Column="1">%</TextBlock>
</Grid>
</Microsoft_Windows_Themes:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsMarkup}" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Microsoft_Windows_Themes:ListBoxChrome SnapsToDevicePixels="true" x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0">$</TextBlock>
<ScrollViewer Grid.Column="1" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost" />
</Grid>
</Microsoft_Windows_Themes:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ToolBar VerticalAlignment="Top" Height="26">
<Button Name="cmdAdd">Add</Button>
<Button Name="cmdProcess">Process</Button>
</ToolBar>
<ListView Grid.Row="1" Margin="3,3,3,0" Name="lvEdit" ItemsSource="{Binding}">
<ListView.View>
<GridView>
<GridViewColumn Header="Item #">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBox Text="{Binding Path=ItemNumber,UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource GridEditStyle}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Price/Markup">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBox Text="{Binding Path=PriceMarkup,UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource GridEditStylePM}" TextAlignment="Right" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="IsMarkup">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<CheckBox IsChecked="{Binding IsMarkup}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<ListView Grid.Row="2" Margin="3" Name="lvStatic" ItemsSource="{Binding}">
<ListView.View>
<GridView>
<GridViewColumn Header="Item #" DisplayMemberBinding="{Binding ItemNumber}" />
<GridViewColumn Header="Price/Markup" DisplayMemberBinding="{Binding PriceMarkup}" />
<GridViewColumn Header="IsMarkup" DisplayMemberBinding="{Binding IsMarkup}" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
Code:
Imports System.ComponentModel
Class Window1
Private bl As BindingList(Of ContractItem)
Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
bl = New BindingList(Of ContractItem)
bl.Add(New ContractItem("001", CDec(12.35), False))
bl.Add(New ContractItem("002", CDec(24), True))
bl.Add(New ContractItem("003", CDec(13.47), False))
bl.Add(New ContractItem("004", CDec(9.86), False))
lvEdit.DataContext = bl
lvStatic.DataContext = bl
End Sub
Private Sub cmdAdd_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles cmdAdd.Click
Dim ci As New ContractItem("", CDec(25), True)
ci.ItemNumber = "-"
bl.Add(ci)
End Sub
Private Sub cmdProcess_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles cmdProcess.Click
Dim sb As New System.Text.StringBuilder
For Each ci As ContractItem In bl
If ci.HasChanged Then
sb.AppendLine(ci.ItemNumber)
End If
Next
MsgBox(sb.ToString)
End Sub
End Class
Code:
Imports System.ComponentModel
Public Class ContractItem
Implements INotifyPropertyChanged
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Private Sub Notify(ByVal propName As String)
_hasChanged = True
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
End Sub
Private _hasChanged As Boolean
Private _itemNumber As String
Private _priceMarkup As Decimal
Private _isMarkup As Boolean
Public Sub New(ByVal itmNum As String, ByVal prcMarkup As Decimal, ByVal is_markup As Boolean)
_itemNumber = itmNum
_priceMarkup = prcMarkup
_isMarkup = is_markup
_hasChanged = False
End Sub
Public ReadOnly Property HasChanged() As Boolean
Get
Return _hasChanged
End Get
End Property
Public Property ItemNumber() As String
Get
Return _itemNumber
End Get
Set(ByVal value As String)
If _itemNumber <> value Then
_itemNumber = value
Notify("ItemNumber")
End If
End Set
End Property
Public Property PriceMarkup() As Decimal
Get
Return _priceMarkup
End Get
Set(ByVal value As Decimal)
If _priceMarkup <> value Then
_priceMarkup = value
Notify("PriceMarkup")
End If
End Set
End Property
Public Property IsMarkup() As Boolean
Get
Return _isMarkup
End Get
Set(ByVal value As Boolean)
If _isMarkup <> value Then
_isMarkup = value
Notify("IsMarkup")
End If
End Set
End Property
End Class