How to get ListView SelectedItem while editing? - c#

I'm trying to save record when combination of keys pressed Ctrl + S.
Below code works fine only when i exit TextBox and select line then press Ctrl + S.
How to SelectItem without exiting TextBox? For example: typing text >> Ctrl + S >> continue typing.
Here is my code:
if (Keyboard.IsKeyDown(Key.LeftCtrl) && Keyboard.IsKeyDown(Key.S))
{
sql.saveSoftwareChanges(_list.SelectedItem as Software);
e.Handled = true;
}
and XAML:
<ListView x:Name="_list" Visibility="Visible" KeyDown="_list_KeyDown">
<!--RESOURCES-->
<ListView.Resources>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="true">
<Setter Property="IsSelected" Value="true" />
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="#FFFFFF9A" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<!--/RESOURCES-->
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button x:Name="_save" Content="Save" MinWidth="20" Width="AUTO" Click="_save_Click" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Product ID">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding productId}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Product">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding product}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Path">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding path}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Master Path">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding master_path}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Parameters">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding parameters}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Windows Version">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding windowsVersion}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

After a lot of research and trial and error I've got the solution.
It's as simple as moving out of that field, which can be achieved by:
MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
and entire method looks like:
if (Keyboard.IsKeyDown(Key.LeftCtrl) && Keyboard.IsKeyDown(Key.S))
{
var uie = e.OriginalSource as UIElement;
uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
sql.saveSoftwareChanges(_list.SelectedItem as Software);
uie.Focus();
e.Handled = true;
}
I hope that will help others as well.

You have to place your save code in a function then call this function from any control that may have the focus at that time. (i.e. the text box as well).
Remember that keyboard events only fire when the corresponding control has focus.
Test this:
<ListView x:Name="_list" Visibility="Visible" KeyDown="_list_KeyDown">
<!--RESOURCES-->
<ListView.Resources>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="true">
<Setter Property="IsSelected" Value="true" />
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="#FFFFFF9A" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<!--/RESOURCES-->
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button x:Name="_save" Content="Save" MinWidth="20" Width="AUTO" Click="_save_Click" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Product ID">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding productId}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Product">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding product}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Path">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding path}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Master Path">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding master_path}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Parameters">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding parameters}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Windows Version">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding windowsVersion}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

Related

wpf - set focus on next textbox on gridviewcolumn

I want to step into next row if I hit a specific key like enter or the arrows on keyboard.I can't find any material on this topic. Could anyone help me out?
I tried with tabnavigation from msdn, but first I want to go on keydown directly to the textbox and second I need to use the arrows and / or the enter key I mentioned earlier.
Thank you!
<ListView AlternationCount="2"
x:Name="lstItems" ItemsSource="{Binding Path=Notes, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Height="300"
KeyboardNavigation.TabNavigation="Cycle"
KeyboardNavigation.AcceptsReturn="False"
SelectedItem="{Binding Path=Current, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
FontSize="{StaticResource h2FontSize}" Margin="5">
<ListView.View>
<GridView x:Name="gridView" ColumnHeaderContainerStyle="{StaticResource itemsListViewHeader}"
>
<GridViewColumn x:Name="Column1" Header="{x:Static p:Resources.DENOMINATION}" Width="200">
<GridViewColumn.HeaderContainerStyle>
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource itemsListViewHeaderLeft}">
</Style>
</GridViewColumn.HeaderContainerStyle>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="BankNoteValue" HorizontalAlignment="Right" Text="{Binding Path=BankNoteValue, StringFormat={}{0:0.##}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn x:Name="Column2" Header="{x:Static p:Resources.PC}" Width="200">
<GridViewColumn.HeaderContainerStyle>
<Style TargetType="GridViewColumnHeader" BasedOn="{StaticResource itemsListViewHeaderLeft}">
</Style>
</GridViewColumn.HeaderContainerStyle>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Width="{Binding ElementName=Column2, Path=ActualWidth, UpdateSourceTrigger=PropertyChanged}" Name="tbAmount"
Text="{Binding Path=BankNotePiece, StringFormat={}{0:#.###}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" IsEnabled="{Binding isChecked}">
</TextBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

How can I group GridViewColumns in WPF, so the expander fills the whole width

I am new to WPF and try to do the following:
I have a ListView with a ItemsSource using a ViewModel.
Inside, there is a GridView with Columns. Each Column represents a Preoperty of the View Model. But the Description is optional and can be rather long. So I want to use a Expander. My Problem is, that I can only manage the expander to be as big as the Name-Column. But I want the expander to be as big as the whole row.
Here are 2 Images to clarify what I want.
My current State:
https://i.stack.imgur.com/ZNA4v.png
What I want to achieve:
https://i.stack.imgur.com/ZmFq1.png
I tried "grouping the GridView" but without success... See here
http://technico.qnownow.com/grouping-gridview-wpf/
Here's my Code
<Window ...>
<Window.Resources>
...
</Window.Resources>
<DockPanel>
<StackPanel DockPanel.Dock="Top">
...
</StackPanel>
<Grid>
<ListView Grid.RowSpan="4" DockPanel.Dock="Top" Margin="10" ItemsSource="{Binding MyView}">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="BorderBrush" Value="Black"></Setter>
<Setter Property="BorderThickness" Value="0,0,0,1"></Setter>
<Setter Property="Focusable" Value="False" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Top"></Setter>
<Setter Property="VerticalContentAlignment" Value="Top"></Setter>
</Style>
</ListView.ItemContainerStyle>
<!-- New GridView -->
<ListView.View>
<GridView>
<!--Number-->
<GridViewColumn Header="#">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="viewModel:MyViewModel">
<TextBlock Text="{Binding Model.Number, StringFormat='#{0}', Mode=OneWay}"
Width="20" TextAlignment="Left" Margin="5" VerticalAlignment="Top" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!--ErrorLevel-->
<GridViewColumn Header="" Width="45">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="viewModel:MyViewModel">
<Image Source="{Binding Model.ErrorLevel, Converter={StaticResource ErrorLevelToImageConverter}, Mode=OneWay}"
ToolTip="{Binding Model.ErrorLevel, Mode=OneWay}" Width="20" Margin="5" VerticalAlignment="Top" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!--ID-->
<GridViewColumn Header="ID">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="viewModel:MyViewModel">
<TextBlock TextAlignment="Center" Margin="5" Width="50" VerticalAlignment="Top" >
<Hyperlink NavigateUri="{Binding Model.Hyperlink, Mode=OneWay}"
Command="{Binding HyperlinkCommand}">
<TextBlock Text="{Binding Model.Id, Mode=OneWay}" />
</Hyperlink>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!--Name-->
<GridViewColumn Header="Name" Width="500" >
<GridViewColumn.CellTemplate>
<DataTemplate DataType="viewModel:MyViewModel">
<Expander ToolTip="Expand" ExpandDirection="Down" Foreground="Black" VerticalAlignment="Top">
<Expander.Header>
<TextBlock Text="{Binding Model.Name, Mode=OneWay}"
HorizontalAlignment="{Binding HorizontalAlignment, RelativeSource={RelativeSource AncestorType=ContentPresenter}, Mode=OneWayToSource}"
TextAlignment="Left" Margin="5" TextWrapping="Wrap" VerticalAlignment="Top" />
</Expander.Header>
<GroupBox Header="Description" FontWeight="Bold" >
<TextBlock Text="{Binding Model.Description, Mode=OneWay}" TextWrapping="Wrap"
FontWeight="Normal" TextAlignment="Left" Margin="5" />
</GroupBox>
</Expander>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!-- Module-->
<GridViewColumn Header="Module" >
<GridViewColumn.CellTemplate>
<DataTemplate DataType="viewModel:MyViewModel">
<TextBlock Text="{Binding Model.Module, Mode=OneWay}"
TextAlignment="Center" Margin="5" Width="100" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</DockPanel>
Once again, i am new to WPF, MVVM, DataBinding and all this. So please try to make your answer as detailed as possible. I tried many things, but they didn't work out.
You could add the following GridViewColumn at the left side (top in XAML) to your GridView
<GridViewColumn Header="" Width="30">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="viewModel:MyViewModel">
<Expander Margin="-5,2,-5000,0" HorizontalAlignment="Left" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type ItemsPresenter}}}">
<GroupBox Header="Description" FontWeight="Bold" Margin="0,0,5,0">
<TextBlock Text="{Binding Model.Description}" FontWeight="Normal" TextWrapping="Wrap" />
</GroupBox>
</Expander>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
This is GridViewColumncontains an empty Header which simply shows the Expander-Arrow in the GridViewRows.
The Expander itself is left aligned and has a huge negative Margin on the right side, so it can draw its content outside of the right boundary. The width is set to the ActualWidth of the ItemsPresenter of your GridView. With this Width you can limit the content to the current visible Width of the GridView (Or you can set it to an absolute value like 500).
And finally a preview of this Column
OK, the fact that the expander is not stretchable is because of the non stretchable parent control. You have a column 'Name' in your gridview with a fixed width and a expander added as a child. As far as i know the child control cannot extend beyond the parent control if this is not truth im sure someone will correct this. I don't know what the best way is to achieve your goal but to give you some inspiration i made a small example.
So, to give you a example if how this could work:
Edit: You can just set negative margins on your expander like so:
<Expander ToolTip="Expand" ExpandDirection="Down" Margin="-100,0,-300,0" Foreground="Black" VerticalAlignment="Top">
Thanks to #LittleBit for this tip.
<ListView x:Name="lsttest" ItemsSource="{Binding persons}">
<ListViewItem>
<StackPanel>
<ListView>
<ListView.View>
<GridView>
<GridViewColumn Header="#1" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"
Width="20" TextAlignment="Left" Margin="5" VerticalAlignment="Top" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Test 2" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"
Width="20" TextAlignment="Left" Margin="5" VerticalAlignment="Top" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Expander ToolTip="Expand" ExpandDirection="Down" Foreground="Black" VerticalAlignment="Top">
<Expander.Header>
<TextBlock Text="{Binding Model.Name, Mode=OneWay}"
HorizontalAlignment="{Binding HorizontalAlignment, RelativeSource={RelativeSource AncestorType=ContentPresenter}, Mode=OneWayToSource}"
TextAlignment="Left" Margin="5" TextWrapping="Wrap" VerticalAlignment="Top" />
</Expander.Header>
<GroupBox Header="Description" FontWeight="Bold" Width="{Binding ActualWidth, ElementName=lsttest}">
<TextBlock Text="{Binding Name, Mode=OneWay}" TextWrapping="Wrap"
FontWeight="Normal" TextAlignment="Left" Margin="5" />
</GroupBox>
</Expander>
</StackPanel>
</ListViewItem>
</ListView>
The result:

WPF How to change the color of a gridviewcolumn

To preface the bulk of the question, I've found several answers regarding CellTemplate and DataTemplate, as well as one setting HeaderContainerStyle, and none of them worked; results ranged from no change to a crash.
I'm trying to change the color of the first entry in each column for my listview (basically so the header for each column sticks out). Here's the most recent thing I've tried with no success. Any suggestions or advice are greatly appreciated.
<ListView Height="380" VerticalAlignment="Top" HorizontalContentAlignment="Stretch">
<ListView.View>
<GridView>
<GridViewColumn Header="First" Width="60" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="Txt" Text="{Binding First}" Background="DarkBlue"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Last" Width="60" DisplayMemberBinding="{Binding Last}" />
<GridViewColumn Header="Group" Width="80" DisplayMemberBinding="{Binding Group}" />
</GridView>
</ListView.View>
</ListView>
Is the following code what you are looking for?
For the first row:
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="Txt" Text="{Binding First}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
<Setter TargetName="Txt" Property="Background" Value="DarkBlue"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</GridViewColumn.CellTemplate>
For the header:
<GridViewColumn Header="First" Width="60" >
<GridViewColumn.HeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Background" Value="LightSkyBlue"/>
</Style>
</GridViewColumn.HeaderContainerStyle>
</GridViewColumn>

Place Popup control on a cell of a ListView

I have a listview and will like to display more info on a popup when a button is pressed. Anyways my listview looks like:
<ListView Name="TableListView">
<ListView.View>
<GridView>
<GridViewColumn Width="50"
Header="ID">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Id}"
HorizontalAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!-- I am having trouble with this column! -->
<GridViewColumn Width="50"
Header="ID">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<Button Content="Click to show more Info">
<Button.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter TargetName="PopupSelectFile"
Property="IsOpen"
Value="True">
</Setter>
</Trigger>
</Button.Triggers>
</Button>
<Popup x:Name="PopupSelectFile">
<Button Width="100"
Height="100"></Button>
</Popup>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
basically I want to show a popup (PopupSelectFile) when the button on the second column is clicked.
<ToggleButton x:Name="theButton">
...
</ToggleButton>
<Popup IsOpen="{Binding IsChecked, ElementName=theButton">
...
</Popup>

How to make a row in listview checked when the row is selected and vice versa in WPF

I am having a listview and using view as gridview as follows:
<ListView Grid.Row="1" Grid.Column="0" Height="100" HorizontalAlignment="Left" Margin="10,10,10,10" Name="listView2" VerticalAlignment="Top" Width="300" ItemsSource="{Binding}" SelectionChanged="listView2_SelectionChanged" SelectionMode="Multiple">
<ListView.View>
<GridView AllowsColumnReorder="True">
<GridViewColumn Header="Select">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=FirstName}" Header="First Name" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=LastName}" Header="Last Name" Width="100"/>
</GridView>
</ListView.View>
</ListView>
Now the issue is that when the user will check on the checkbox the record should get selected. Also is the user selects the record from the list then the corresponding checkboxes should be selected.
How to do it ?
I'm assuming that your view model has IsSelected property:
public Boolean IsSelected
{
get { return isSelected; }
set
{
if (isSelected != value)
{
isSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
private Boolean isSelected;
So, let's change markup:
<ListView ItemsSource="{Binding}" SelectionMode="Multiple">
<!-- add style for the item in list view: -->
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView AllowsColumnReorder="True">
<GridViewColumn Header="Select">
<GridViewColumn.CellTemplate>
<DataTemplate>
<!-- bind the checkbox to the IsSelected property: -->
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Name" Width="100"/>
</GridView>
</ListView.View>
</ListView>
The simplest ways:
<GridViewColumn Header="None">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Width="50"
Height="50"
IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}},
Path=IsSelected,Mode=TwoWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>

Categories

Resources