I'm trying to populate and navigation panel dynamicaly in a ListView
<ListView Background="Transparent" HorizontalAlignment="Center" x:Name="viewItemControl" ItemsSource="{Binding Views}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Button Style="{StaticResource PluginViewButton}"
Command="{Binding ElementName=viewItemControl,Path=DataContext.NavigateCommand}"
CommandParameter="{Binding ViewName}"
BorderThickness="{Binding Path = ViewObj.DataContext.IsSelected, Converter={StaticResource BoolToThicknessConverter},Mode=OneWay}">
<Button.Content>
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="15"/>
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="{Binding Icon, Mode=OneTime}"></Image>
<TextBlock Grid.Row="1" Text="{Binding DisplayableName}" HorizontalAlignment="Center"/>
</Grid>
</Button.Content>
</Button>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Focusable" Value="false"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
The list view is binded to a collection of ViewInfo Objects
public class ViewInfo
{
public ViewInfo(IPluggableView view)
{
ViewName = view.ViewName;
DisplayableName = view.DisplayableName;
DisplayRank = view.DisplayRank;
Icon = view.Icon;
ViewModelType = view.ViewModelType;
ViewObj = view;
}
public IPluggableView ViewObj { get; set; }
public string ViewName { get; set; }
public string DisplayableName { get; set; }
public Type ViewModelType { get;set; }
public int DisplayRank { get; set; }
public BitmapSource Icon { get; set; }
}
The Interface IPluggableView is implemented by all of my usercontrols which are views
My viewmodel base class has a property IsSelected. Viewmodel class is implementing prism INavigationAware interface, so in OnNavigatedTo and OnNavigatedFrom functions i'm updating the IsSelected property.
I want my buttons border to be thicker when it's view is selected and it should go back to default when i navigate to another view as given below.
So i wrote BoolToThickness converter which simply returns 0.5 or 2 depending on the value.
The problem I face is that it's only updating once at Load time, then never updated after that eventhough i update IsSelected property.
I'm kind of sure that the UI is not getting the RaisePropertyChanged event. but i'm know sure how to solve this problem. If this is a design issue please help me rectify it.
You should define the ItemContainerStyle
and trigger on IsSelected
directly. To override the ControlTemplate
is only necessary if you want to modify or remove the default highlight behavior:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="BorderBrush"
Value="Black" />
<!-- Optional -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- Change border thickness on item is selected -->
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness" Value="3" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
Additionally you should bind the ListView.SelectedItem
to your view model to control the current selection.
But if you still want to use a value conveter then you should adjust the binding on the BorderThickness
:
<Button BorderThickness="{Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=ListViewItem}, Path=IsSelected, Converter={StaticResource BoolToThicknessConverter}}">