omarmallat
omarmallat

Reputation: 734

set the content of togglebutton based on condition in xaml

I don't have that much experiences in WPF and XAML files, and maybe my question is very simple. so let me get your help if possible.

As a brief, it's a survey system that will go through some questions, where each question has exactly three answers. Answers are in a ListBox.

In order to make it easier for illiterate people, I want that the ToogleButton in each answer to have different shape: 1st is square, 2nd is Circle and 3rd is Triangle. my objective is to set the shape based on the ListBoxItem index.

Code is below with a static shape (Currently Triangle):

<ListBox x:Name="AnswersListBox" Margin="0 16 0 16" ItemsSource="{Binding Path=CurrentQuestion.Answers, ElementName=Questionctl}" Grid.Row="1">
<ListBox.ItemTemplate>
    <DataTemplate DataType="{x:Type DAL:Answer}">
        <Grid Height="85">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="80"/>
                <ColumnDefinition Width="300*"/>
            </Grid.ColumnDefinitions>

            <ToggleButton Margin="10 0" Style="{StaticResource MaterialDesignActionToggleButton}" ToolTip="Click to Select" VerticalAlignment="Center"                        
            IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}">
                <Viewbox Width="32" Height="32">
                    <Canvas Width="32" Height="32">
                        <Path Data="M12,2L1,21H23M12,6L19.53,19H4.47" Width="32" Height="32" Stretch="Fill"
                        Fill="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ToggleButton}}, Path=Foreground}"/>
                    </Canvas>
                </Viewbox>

            </ToggleButton>

            <TextBlock Text="{Binding Path=AnswerID, Converter={StaticResource AnswerTextConverter}}" VerticalAlignment="Center" TextWrapping="Wrap" 
                   Foreground="#424242" Grid.Column="1" FontSize="24"/>
        </Grid>
    </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

I want to change the property Data of the object Path based on the Main Container's index which is a ListBoxItem. Most probably, I have to use triggers to set the Data value based on the index number of the ListBoxItem, but unable to do that...

Is that possible?

Upvotes: 0

Views: 1013

Answers (2)

omarmallat
omarmallat

Reputation: 734

Many Thanks to @Subramaniam B, and based on his Answer which requires a few changes in the binding of the DataTrigger where it should be:

<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
                                                                   Path=(ItemsControl.AlternationIndex)}" Value="0">
                                                        <Setter Property="Data" Value="M28.3,28.3H0L14.2,0L28.3,28.3z M2.9,26.6h22.5L14.2,4L2.9,26.6z"/>
                                                    </DataTrigger>

and the full code will be:

                <ListBox x:Name="AnswersListBox" AlternationCount="3">
                <ListBox.ItemTemplate>
                    <DataTemplate DataType="{x:Type DAL:Answer}">
                            <ToggleButton Style="{StaticResource myCheckboxToggleButtonWithInsideCheck}" ToolTip="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=(ItemsControl.AlternationIndex)}"                        
                                            IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}">
                                <Viewbox Width="60" Height="60">
                                    <Canvas Width="32" Height="32">
                                    <Path Fill="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Label}}, Path=Foreground}" Height="32" Stretch="Fill" Width="32">
                                        <Path.Style>
                                            <Style TargetType="{x:Type Path}">
                                                <Style.Triggers>
                                                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
                                                                   Path=(ItemsControl.AlternationIndex)}" Value="0">
                                                        <Setter Property="Data" Value="M16.2,28.3h-4.1C0.5,28.3,0,27.9,0,16.2v-4.1C0,0.5,0.5,0,12.1,0h4.1c11.7,0,12.1,0.5,12.1,12.1v4.1C28.3,27.9,27.9,28.3,16.2,28.3z M12.1,1.9C7,1.9,4.1,1.9,3,3s-1.1,4-1.1,9.1v4.1c0,5.2,0,8,1.1,9.1c1.1,1.1,4,1.1,9.1,1.1h4.1c5.2,0,8,0,9.1-1.1c1.1-1.1,1.1-4,1.1-9.1v-4.1c0-5.2,0-8-1.1-9.1c-1.1-1.1-4-1.1-9.1-1.1H12.1z"/>
                                                    </DataTrigger>
                                                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
                                                                   Path=(ItemsControl.AlternationIndex)}" Value="1">
                                                        <Setter Property="Data" Value="M28.3,28.3H0L14.2,0L28.3,28.3z M2.9,26.6h22.5L14.2,4L2.9,26.6z"/>
                                                    </DataTrigger>
                                                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
                                                                   Path=(ItemsControl.AlternationIndex)}" Value="2">
                                                        <Setter Property="Data" Value="M14.2,28.3C6.4,28.3,0,22,0,14.2S6.4,0,14.2,0s14.2,6.4,14.2,14.2S22,28.3,14.2,28.3z M14.2,2.2c-6.6,0-12,5.4-12,12c0,6.6,5.4,12,12,12c6.6,0,12-5.4,12-12C26.2,7.6,20.8,2.2,14.2,2.2z"/>
                                                    </DataTrigger>
                                                </Style.Triggers>
                                            </Style>
                                        </Path.Style>

                                    </Path>
                                </Canvas>
                                </Viewbox>
                            </ToggleButton>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

Upvotes: 0

Subru
Subru

Reputation: 353

In ListBox, there are no direct properties to get the index of the item. However, the same can be achieved by setting the AlternationCount and accessing AlternationIndex.

<ListBox x:Name="AnswersListBox" 
             Margin="0 16 0 16" 
             ItemsSource="{Binding Path=Answers}" 
             Grid.Row="1"
             AlternationCount="100">
        <ListBox.ItemTemplate>
            <DataTemplate DataType="{x:Type DAL:Answer}">
                <Grid Height="85">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="80"/>
                        <ColumnDefinition Width="300*"/>
                    </Grid.ColumnDefinitions>

                    <ToggleButton Margin="10 0" Style="{StaticResource MaterialDesignActionToggleButton}" ToolTip="Click to Select" VerticalAlignment="Center"                        
                                  IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}">
                        <Viewbox Width="32" Height="32">
                            <Canvas Width="32" Height="32">
                                <Path Width="32" Height="32" Stretch="Fill"
                                      Fill="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ToggleButton}}, Path=Foreground}">
                                    <Path.Style>
                                        <Style TargetType="{x:Type Path}">
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
                                                                       Path=(ItemsControl.AlternationIndex)}" Value="0">
                                                    <Setter Property="Data" Value="M12,2L1,21H23M12,6L19.53,19H4.47"/>
                                                </DataTrigger>
                                                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
                                                                       Path=(ItemsControl.AlternationIndex)}" Value="1">
                                                    <Setter Property="Data" Value="M12,2L1,21H23M12,6L19.53,19H4.47"/>
                                                </DataTrigger>
                                                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
                                                                       Path=(ItemsControl.AlternationIndex)}" Value="2">
                                                    <Setter Property="Data" Value="M12,2L1,21H23M12,6L19.53,19H4.47"/>
                                                </DataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </Path.Style>
                                </Path>
                            </Canvas>
                        </Viewbox>

                    </ToggleButton>

                    <TextBlock Text="{Binding Path=AnswerID, Converter={StaticResource AnswerTextConverter}}" VerticalAlignment="Center" TextWrapping="Wrap" 
               Foreground="#424242" Grid.Column="1" FontSize="24"/>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

Replace the Value of Data with the required shape.

Upvotes: 1

Related Questions