Search code examples
c#.netwpfxaml.net-4.8

XAML Collapsed bullet point list with hyperlink


Need some pointers on XAML styling for a collapsed bullet point list with a hyperlink to display all data items, i.e. show only the first option by default, with some hyperlink text which when clicked, would display the remaining items in the list. E.g.:

Collapsed List

Expanded List on clicking "Click me"

  • Option 1
  • Option 2
  • Option 3....

Solution

  • Not sure if this is exactly what you're asking for. Generally this is not a "Please write code for me" website

    enter image description here

    That said, here's some code

    It's not terribly difficult to do what you're asking. You just need to create a custom user control. Below is the Xaml and Xaml.cs for a custom user control I made for you

    SampleCollapsedList.xaml.cs

    public partial class SampleCollapsedList : UserControl, INotifyPropertyChanged
    {
                public bool IsExpanded { get; set; }
                public string FirstItem
                {
                    get
                    {
                        return ListItems != null && ListItems.Count > 0 ? ListItems?.First() : string.Empty;
                    }
                }
        
                public ObservableCollection<string> ListItems
                {
                    get { return (ObservableCollection<string>)GetValue(ListItemsProperty); }
                    set { SetValue(ListItemsProperty, value); }
                }
        
                public static readonly DependencyProperty ListItemsProperty =
                    DependencyProperty.Register(nameof(ListItems), typeof(ObservableCollection<string>), typeof(SampleCollapsedList), new PropertyMetadata(null,CollectionUpdated));
        
        
                public event PropertyChangedEventHandler PropertyChanged;
        
                public SampleCollapsedList()
                {
                    InitializeComponent();
                }
        
                private static void CollectionUpdated(DependencyObject d, DependencyPropertyChangedEventArgs e)
                {
                    if (d is SampleCollapsedList sampleCollapsedList)
                    {
                        sampleCollapsedList.OnPropertyChanged(nameof(FirstItem));
                    }
                }
        
                private void OnHyperlinkClicked(object sender, RoutedEventArgs e)
                {
                    IsExpanded = !IsExpanded;
                    OnPropertyChanged(nameof(IsExpanded));
                }
        
                private void OnPropertyChanged(string propName)
                {
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
                }
    }
    

    SampleCollapsedList.xaml

    <UserControl x:Class="WpfApp1.SampleCollapsedList"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:local="clr-namespace:WpfApp1"
                 mc:Ignorable="d"
                 d:DesignHeight="450"
                 d:DesignWidth="800"
                 x:Name="self">
    
        <UserControl.Resources>
            <local:BoolToVisConverter x:Key="BoolToVisibilityConverter" />
        </UserControl.Resources>
        <Grid Height="250"
              Width="500">
            <StackPanel Orientation="Vertical"
                        Visibility="{Binding Path=IsExpanded, ElementName=self, Converter={StaticResource ResourceKey=BoolToVisibilityConverter}, ConverterParameter=opposite}">
                <TextBlock Text="{Binding Path=FirstItem, ElementName=self}" />
                <TextBlock><Hyperlink Click="OnHyperlinkClicked">Click Me</Hyperlink></TextBlock>
            </StackPanel>
            <ListBox Visibility="{Binding Path=IsExpanded, ElementName=self, Converter={StaticResource ResourceKey=BoolToVisibilityConverter}}"
                     ItemsSource="{Binding Path=ListItems, ElementName=self}"
                     BorderThickness="0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock><Run>- </Run><Run Text="{Binding Path=.}" /></TextBlock>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </UserControl>
    
    

    Also a simple converter to make the hide show magic happen

    using System;
    using System.Globalization;
    using System.Windows.Data;
    using System.Windows;
    
    namespace WpfApp1
    {
        public class BoolToVisConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if(parameter is string param && param.ToLower().Contains("opposite"))
                {
                    return (bool)value ? Visibility.Collapsed : Visibility.Visible;
                }
                else
                {
                    return (bool)value ? Visibility.Visible : Visibility.Collapsed;
                }
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    }