How to select listview item when clicking button - c#

Inside my listview I´ve created a control template. Inside this template I made a button, so that every item inside mit listview has a button. This button represents an link which opens the directory that is shown. When I click the button, my program opens the explorer as I expect it. But when I click the button of an item that is not selected it opens the path of the selected item. So my question is, how can I change the selected item when I click the button inside my listview.
Here is how it looks like:
As you can see "R1" is selected, but I click on the link of "R3". What happens is, that C:\Temp\Folder1 gets opened, because "R1" is still the selecteditem. What I wish to is that C:\Temp\Folder3 gets opend. I think the trick should be that "R3" gets selected when clicking the button that represents the link. Does anyone know how to that?
This is my XAML-Code:
<ListView Grid.Row="1" ItemsSource="{Binding MyCollection}" FontSize="20" SelectedItem="{Binding SelectedMember, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="7,10,7,0" x:Name="ListView1" SelectionChanged="ListView1_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn Header="Header 1" Width="150"/>
<GridViewColumn Header="Header 2" Width="120"/>
<GridViewColumn Header="Header 3" Width="120"/>
<GridViewColumn Header="Header 4" Width="560"/>
<GridViewColumn Header="Header 5" Width="100"/>
</GridView>
</ListView.View>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<EventSetter Event="MouseDoubleClick" Handler="ListViewItem_MouseDoubleClick"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="560"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" Content="{Binding ID}" HorizontalAlignment="Center"/>
<ContentPresenter Grid.Column="1" Content="{Binding Name}" HorizontalAlignment="Center"/>
<ContentPresenter Grid.Column="2" Content="{Binding Description}" HorizontalAlignment="Center"/>
<Button Grid.Column="3" Content="{Binding Path}" Style="{StaticResource Link}" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.GoToPathCommand }" HorizontalAlignment="Left" Margin="5,0,0,0" IsEnabled="{Binding ButtonEnabled}"/>
<ContentPresenter Grid.Column="4" Content="{Binding Owner}" HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="DarkBlue"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>

Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.GoToPathCommand }"
This Command will jump to the Cmd of the ViewModel. I assume that the Command will check which item is selected and it will access it's property Path.
Avoiding this behavior, You can create a Command that will take a parameter and set it from Binding:
<Button Content="{Binding Path}"
Command="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}, Path=DataContext.GoToPathCommand }"
CommandParameter="{Binding Path}"/>
Now the command itself must be adjusted:
public MyCmd : ICommand
{
public void Execute(object parameter)
{
string path = (string) parameter;
//Open the path via explorer
}
}

Try adding below trigger too in the ListViewItem Style
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True"/>
</Trigger>
</Style.Triggers>

Related

gridview column auto size not working on loading except with hot reload

When I load my list, my column size is set to "auto". I would like my column to automatically take the size of my longest string, so as not to "cut" the strings.
For the first column, we see that everything is fine. For the second one, which is exactly the same except for the font style, it doesn't work, we see that the names are cut.
However, if I change "auto" to a value, for example 10, and then back to "auto", everything works with an horizontal scrollbar:
If it works with hot reload and for the first column, what can explain that my second column does not fit the size of my strings?
My list is a collection of objects composed with 2 strings. My code :
<ListView
BorderBrush="SteelBlue"
ItemsSource="{Binding ListeAgentsAAfficher}"
SelectedItem="{Binding AgentSelected}">
<ListView.ContextMenu>
<ContextMenu>
<MenuItem
Command="{Binding AfficherSupprimerCommand}"
Header="Afficher agents supprimés"
IsCheckable="True"
IsChecked="{Binding IsCheckedSupprimer}" />
<MenuItem
Command="{Binding TriAgentsMatriculesCommand}"
Header="Trier par matricules"
IsCheckable="True"
IsChecked="{Binding IsCheckedTriMatricule}" />
<MenuItem
Command="{Binding TriAgentsNomCommand}"
Header="Trier par noms"
IsCheckable="True"
IsChecked="{Binding IsCheckedTriNom}" />
</ContextMenu>
</ListView.ContextMenu>
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding Supprimer}" Value="true">
<Setter Property="Foreground" Value="DarkOrange" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Visibility" Value="Collapsed" />
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn Width="auto">
<GridViewColumnHeader />
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
HorizontalAlignment="center"
VerticalAlignment="center"
FontSize="10"
FontWeight="Bold"
Text="{Binding Matricule}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
HorizontalAlignment="center"
VerticalAlignment="center"
Text="{Binding Nom}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

Dynamically generated buttons seem to not fire their commands?

I have a ListBox which is dynamically filled during runtime. It has a DataType of RequirementPreview which is needed to bind certain properties to triggers, sources and parameters. There is, however, 1 command-binding that needs to trigger a command that is set in the datacontext but has nothing to do with the template datatype.
What I want is that the Button fires the 'RevertDelete'-command and sends the Guid of the RequirementPreview to which the button belongs. As of now, nothing happens when I press the button.
Xaml:
<ListBox Grid.Row="1" Grid.ColumnSpan="3" Margin="5" IsEnabled="{Binding IsEnabled}" ItemsSource="{Binding Requirements}" SelectionMode="Extended">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand Command="{Binding SelectionChanged}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDeleted}" Value="True">
<Setter Property="Foreground" Value="red"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type myModels:RequirementPreview}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="45"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Name}" ToolTip="{Binding Name}" HorizontalAlignment="Stretch"/>
<Button Grid.Column="2" HorizontalAlignment="Right" IsEnabled="{Binding IsEnabled}" Visibility="{Binding IsDeleted, Converter={StaticResource BoolToVisibility}}"
Command="{Binding RevertDelete}" CommandParameter="{Binding Guid}" Height="10" Width="10"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Xaml.cs:
[Dependency]
public IMainViewModel ViewModel
{
get { return this.DataContext as IMainViewModel; }
set { this.DataContext = value; }
}
Edit:
Tried messing around with the databinding;
Command="{Binding RelativeSource={x:Static RelativeSource.PreviousData}, Path=RevertDelete}"
Command="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=RevertDelete}"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=RevertDelete}
Neither made a difference.
I guess RevertDelete command is not a part of RequirementPreview type which works as a data context for the template. You'll need to use relative source binding for this command:
<Button Command="{Binding DataContext.RevertDelete, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding Guid}" />

Update Grid Row Cell Image when a user selects image from dialog

I have an Image and a button side by side in a DevExpress grid, when the user clicks the button I would like the user to be able to select from a FileDialog a new image that should immediately show in the Image Field. When the user updates the rest of the fields in the row the IPropertyChange event should fire and store the row. How can I achieve this in WPF?
XAML:
<dxg:GridColumn FieldName="Image" Header="Image" >
<dxg:GridColumn.CellTemplate>
<DataTemplate>
<DockPanel>
<Image Source="{Binding RowData.Row.Image, Converter={StaticResource BinaryImageConverter}}" Width="100" />
<Button x:Name="BrowseFilePath" Height="20" Width="20" Content="..." Visibility="Hidden" CommandParameter="{Binding RowData.Row}" />
<!--<Button x:Name="BrowseFilePath" Height="20" Width="20" Content="..." Visibility="Hidden" Command="{Binding Source={x:Static local:FacilitiesBrowseImagePathDialog.BrowsePathCommand}}" CommandParameter="{Binding RowData.Row}" />-->
</DockPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dxg:GridRow}}" Value="True">
<Setter TargetName="BrowseFilePath" Property="Visibility" Value="Visible" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</dxg:GridColumn.CellTemplate>
</dxg:GridColumn>

Ability to click on a button as part of a background style WPF

I have a ListBox that sometimes contains no items. If this ListBox contains no items, then a watermark and a notification in the form of a button with a tool tip will be displayed. I originally had the button at the bottom right corner of my screen. But it was requested I move the button to a more central location, specifically just below the watermark in the ListBox. I moved the button to the background of the ListBox initially but that did not work because I was unable to get the tool tip or press the button. My question is: Is there a way to have the button function properly on the background of the ListBox.
Style:
<VisualBrush x:Key="WatermarkStyle" Stretch="None" AlignmentX="Center" AlignmentY="Center">
<VisualBrush.Visual>
<Grid>
<Button
Margin="0,50,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding ReloadCommand}"
ToolTip="{Binding Path=NotificationTip}"
Visibility="{Binding Path=ShowNotification,
Converter={StaticResource TrueToVisibleConverter}}"
Style="{StaticResource StaticStyle}"
IsEnabled="{Binding Path=CanReload}">
<Image Source="{Binding Path=NotificationIcon}" Stretch="Uniform" Width="35"/>
</Button>
<TextBlock FontFamily="SEGOEWP" FontSize="22" FontWeight="Normal" HorizontalAlignment="Center"
VerticalAlignment="Center" Foreground="Gray" Opacity="1" Text="{Binding BackgroundWatermark}"/>
</Grid>
</VisualBrush.Visual>
</VisualBrush>
ListBox:
<ListBox x:Name="ListBox"
Grid.Row="2"
Grid.ColumnSpan="3"
BorderThickness="1"
ItemsSource="{Binding Path=ListView}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding SelectedDevice}"
SelectionMode="Single">
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding HasItems, RelativeSource={RelativeSource Self}}" Value="False">
<Setter Property="Background" Value="{StaticResource WatermarkStyle}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>

Button Will Not Fire from Style

Yeah, im not sure what i have done. brain feels like swiss cheese
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Focusable" Value="False"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Command" Value="{Binding CommandButtonClicked}"/>
<Setter Property="CommandParameter" Value="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}"/>
</Style>
</Window.Resources>
Button that will Fire.
<Grid DockPanel.Dock="Top">
<TextBox BorderBrush="Transparent" BorderThickness="0" x:Name="txtInput" Padding="50,10,15,15" AcceptsReturn="True" TextChanged="txtInput_TextChanged" TextWrapping="Wrap" Foreground="Crimson" Text="{Binding UserInput, Mode=TwoWay}" Background="Transparent"/>
<Button Width="30" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,3,0,0">
<Image Source="Images/Actions list add user.ico" />
</Button>
</Grid>
Buttons that will not fire
<ListView x:Name="ListViewUsers" ItemsSource="{Binding UserNames}" DockPanel.Dock="Top" Foreground="Green" BorderBrush="Transparent">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.HeaderTemplate>
<DataTemplate>
<Button Margin="3,0,3,0" Width="30">
<Image Source="Images/Actions user group delete.ico"/>
</Button>
</DataTemplate>
</GridViewColumn.HeaderTemplate>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button>
<Image Source="Images/Actions list remove user.ico" Width="25"/>
</Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="User ID" DisplayMemberBinding="{Binding}"/>
</GridView>
</ListView.View>
</ListView>
i have also tried adding in a separate DelegateCommand per button, but that doesnt help either. it seems to be anything that inside this ListView and is Generated at runtime after the initial render will not fire.
any ideas ?
In the "cell" DataTemplate it will have its DataContext set to the "item" within the data collection assigned to the ListView for which the "look" is being provided i.e. a "username".
But your style is using a binding that needs to access the object that contains the "CommandButtonClicked" property.
Thus you need a way to get back to the DataContext that is holding your "CommandButtonClicked" property.....so assuming you had set your "ViewModel" onto your Windows DataContext you could do this...
<ListView x:Name="ListViewUsers" ItemsSource="{Binding UserNames}" DockPanel.Dock="Top" Foreground="Green" BorderBrush="Transparent">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.HeaderTemplate>
<DataTemplate>
<Button Margin="3,0,3,0" Width="30" DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext}">
<Image Source="Images/Actions user group delete.ico"/>
</Button>
</DataTemplate>
</GridViewColumn.HeaderTemplate>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext}">
<Image Source="Images/Actions list remove user.ico" Width="25"/>
</Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="User ID" DisplayMemberBinding="{Binding}"/>
</GridView>
</ListView.View>
</ListView>
There are alternative ways to do what you are doing...just one suggestion...look up routed commands (you could define one and then use it in your style e.g. Command="{x:Static mynamespace::MyCommands.DoSomething}" and then set up a CommandBinding to handle them).

Categories

Resources