How to create a ListView in WPF with groupers and element counter in each group?

0

Based on this tutorial I created a ListView with different groupers.

But I need to show the amount of elements within each group and the description of each, I am not allowed to use the generic word "Element (s)" in the groups, it has to be more personalized.

For example:

Primer Grupo  (2 Segundos Grupos)
      Segundo Grupo  (1 Tercer Grupo)
          Tercer Grupo 3  (2 Elementos)
              Elemento 1
              Elemento 2
      Segundo Grupo  (2 Terceros Grupos)
          Tercer Grupo  (3 Elementos)
              Elemento 1
              Elemento 2
              Elemento 3
          Tercer Grupo  (1 Elementos)
              Elemento 1

The aforementioned tutorial uses the following block of code to show the number of elements (the ItemCount ), but that amount is the total of elements, that is, the total of the elements of the last level, based on my example said total would have a value of 6 .

<ListView.GroupStyle>
    <GroupStyle>
        <GroupStyle.ContainerStyle>
            <Style TargetType="{x:Type GroupItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Expander IsExpanded="True">
                                <Expander.Header>
                                    <StackPanel Orientation="Horizontal">
                                        <TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="Gray" FontSize="22" VerticalAlignment="Bottom" />
                                        <TextBlock Text="{Binding ItemCount}" FontSize="22" Foreground="Green" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />
                                        <TextBlock Text=" item(s)" FontSize="22" Foreground="Silver" FontStyle="Italic" VerticalAlignment="Bottom" />
                                    </StackPanel>
                                </Expander.Header>
                                <ItemsPresenter />
                            </Expander>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </GroupStyle.ContainerStyle>
    </GroupStyle>
</ListView.GroupStyle>
    
asked by Tecnologer 05.04.2017 в 03:15
source

1 answer

0

To solve this problem I found an interesting interface IMultiValueConverter . The interface is implemented and the property Text of the element TextBlock (or any other element that supports MultiBinding ) links the implementation of the interface to the property Converter of MultiBinding .

Based on the previous code:

<!-- lineas de codigo ignoradas -->
<TextBlock Text="{Binding ItemCount}" FontSize="22" Foreground="Green" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />
<TextBlock Text=" item(s)" FontSize="22" Foreground="Silver" FontStyle="Italic" VerticalAlignment="Bottom" />
<!-- lineas de codigo ignoradas -->

Solution:

XAML
It is necessary to create a resource for UserControl

<UserControl.Resources>
    <self:ClaseImplentacion x:Key="AliasDeLaClase" />
</UserControl.Resources>
  

Where self is the namespace where the class is located.

Previous TextBlock will be replaced by the following:

<TextBlock FontSize="22" Foreground="Green" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />
    <TextBlock.Text>
        <MultiBinding Converter="{StaticResource AliasDeLaClase}">
            <!-- Con esto se pasa el Objeto que pertenece al grupo -->
            <Binding Path="" />
            <!-- Y este se pasa para que se actualice la informacion -->
            <Binding Path="ItemCount" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Interface implementation IMultiValueConverter

public class ClaseImplentacion: IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        try
        {
            CollectionViewGroup group = values[0] as CollectionViewGroup;

            var depth = GetDepth((string)group.Name);
            var label = "";
            switch (depth)
            {
                case 0://level protocol
                    label += string.Format(group.Items.Count + " Segundo{0} Grupo{0}", group.Items.Count > 1 ? "s" : "");
                    break;
                case 1://level channel
                    label += string.Format(group.Items.Count + " Tercer{0} Grupo{1}", group.Items.Count > 1 ? "os" : "", group.Items.Count > 1 ? "s" : "");
                    break;
                case 2://level pan
                    label += string.Format(values[1] + " Elemento{0}", (int)values[1] > 1 ? "s" : "");
                    break;
            }

            return "   (" + label + ")";
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.Message);
            return "";
        }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    //la forma de buscar en que nivel de grupo estoy, en este caso busco palabras clave que determinan la profundidad
    private byte GetDepth(string group)
    {
        Regex rgx = new Regex(".*primer.*", RegexOptions.IgnoreCase);

        if (rgx.Match(group).Length > 0)
            return 0;

        rgx = new Regex(".*segundo.*", RegexOptions.IgnoreCase);
        if (rgx.Match(group).Length > 0)
            return 1;

        rgx = new Regex(".*tercer.*", RegexOptions.IgnoreCase);
        if (rgx.Match(group).Length > 0)
            return 2;

        return 3;//elemento
    }
}
  

This form can also be used to create a Tooltip .

I hope to help with this question-answer.

    
answered by 05.04.2017 / 03:15
source