I have a ListView with a bunch of people in it that supports multiple selection. I want to have it so that when a person is selected by way of the checkbox that additional controls appear - in this case a StackPanel containing some TimePicker controls becomes visible.
When the person is unselected the StackPanel should revert to being invisible.
My current code:
XAML:
<ContentDialog.Resources>
<DataTemplate x:Key="ContactListViewTemplate" x:DataType="model:Client">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse x:Name="Ellipse"
Grid.RowSpan="2"
Width ="32"
Height="32"
Margin="6"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Fill="{ThemeResource SystemControlBackgroundBaseMediumBrush}"/>
<TextBlock Grid.Column="1"
Text="{x:Bind FirstName}"
x:Phase="1"
Style="{ThemeResource BaseTextBlockStyle}"
Margin="12,6,0,0"/>
<TextBlock Grid.Column="1"
Grid.Row="1"
Text="{x:Bind LastName}"
x:Phase="2"
Style="{ThemeResource BodyTextBlockStyle}"
Margin="12,0,0,6"/>
<StackPanel Orientation="Horizontal" x:Name="timePanel" Grid.Column="2" Grid.RowSpan="2" Visibility="Collapsed">
<TimePicker Header="Start"></TimePicker>
<TimePicker Header="End"></TimePicker>
</StackPanel>
</Grid>
</DataTemplate>
</ContentDialog.Resources>
<ListView x:Name="clientsList" SelectionMode="Multiple" ItemTemplate="{StaticResource ContactListViewTemplate}" SelectionChanged="ClientsList_SelectionChanged" />
Code Behind:
private void ClientsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Debug.WriteLine("called mett " + e.AddedItems.Count);
var listView= sender as ListView;
if(e.RemovedItems.Count > 0)
{
}
if(e.AddedItems.Count > 0)
{
foreach(var item in e.AddedItems)
{
ListViewItem myListViewItem = (ListViewItem)item;
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListViewItem);
StackPanel stackPanel = myContentPresenter.ContentTemplate.FindDescendant("timePanel") as StackPanel;
}
}
}
Let me show you one way to do this by using the Loaded
event on your timePanel.
private void TimePanel_Loaded(object sender, RoutedEventArgs e)
{
if (sender is not StackPanel timePanel ||
timePanel.FindAscendant<ListView>() is not ListView listView ||
timePanel.DataContext is not object dataContext ||
listView.ContainerFromItem(dataContext) is not ListViewItem listViewItem)
{
return;
}
timePanel.SetBinding(
VisibilityProperty,
new Binding
{
Source = listViewItem,
Path = new PropertyPath("IsSelected"),
Mode = BindingMode.OneWay,
Converter = new TrueToVisibleConverter(),
});
}
and the TrueToVisibleConverter
should be something like this:
public class TrueToVisibleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return value is bool boolValue && boolValue is true
? Visibility.Visible
: Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
BTW, the FindAscendant
extension method comes from the CommunityToolkit.WinUI.Extensions NuGet package.