ItemsControl comma separated values in UWP app

2020-03-31 09:21发布

I am trying to bind name with comma-separated values. In the last item I don't want to add a comma. Can you please let me know how to remove the last comma in WinRT application?

<ItemsControl ItemsSource="{Binding xxxx}" >
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal"></StackPanel>
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal" Margin="0,-6,0,0" >    
                                        <HyperlinkButton x:Name="name" Content="{Binding Name}" VerticalAlignment="Top" Style="{ThemeResource TileContentHyperlinkStyle}"  ></HyperlinkButton>
                                        <TextBlock x:Name="Comma" x:Uid="/Resources/Comma" Style="{ThemeResource TileContentStyle}" VerticalAlignment="Center" Margin="0,0,5,0" />
                                    </StackPanel>
                             </DataTemplate>
                            </ItemsControl.ItemTemplate>  

Example output:

Ramesh ,Sutha,Nikhil, <=== (need to remove last comma)

1条回答
家丑人穷心不美
2楼-- · 2020-03-31 09:51

You can add a flag in your view model to detect whether to show the comma. For example:

In MyViewModel, add a IsLast property as the flag:

public class MyViewModel
{
    public string Name { get; set; }

    public bool IsLast { get; set; } = false;
}

Then in XAML, bind the Visibility property of TextBlock to IsLast:

<ItemsControl ItemsSource="{Binding }">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Margin="0,-6,0,0" Orientation="Horizontal">
                <HyperlinkButton x:Name="suspectname"
                                 VerticalAlignment="Top"
                                 Content="{Binding Name}"
                                 Style="{ThemeResource IncidentSmallTileContentHyperlinkStyle}" />
                <TextBlock x:Uid="/Resources/Comma"
                           x:Name="Comma"
                           Margin="0,0,5,0"
                           VerticalAlignment="Center"
                           Style="{ThemeResource IncidentSmallTileContentStyle}"
                           Visibility="{Binding IsLast,
                                                Converter={StaticResource MyVisibilityConverter}}" />
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Here we need a Converter to convert bool to Visibility:

public class MyVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var isLast = (bool)value;
        if (isLast)
        {
            return Visibility.Collapsed;
        }
        else
        {
            return Visibility.Visible;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

After this, we can add some data to have a test:

public MainPage()
{
    this.InitializeComponent();

    List<MyViewModel> MyList = new List<MyViewModel>() {
        new MyViewModel() { Name = "Ramesh" },
        new MyViewModel() { Name = "Sutha" },
        new MyViewModel() { Name = "Nikhil", IsLast = true }
    };
    this.DataContext = MyList;
}

Update:

Adding a flag for comma in the viewmodel is not a good approach. Using a data template selector to switch between a template with and without the comma may be a better way.

To do this, we need two templates first, the template for the first item should have no comma and the others need a comma:

<DataTemplate x:Key="CommonDataTemplate">
    <StackPanel Margin="0,-6,0,0" Orientation="Horizontal">
        <TextBlock x:Name="Comma"
                   Margin="0,0,5,0"
                   VerticalAlignment="Center"
                   Text="," />
        <HyperlinkButton x:Name="suspectname"
                         VerticalAlignment="Top"
                         Content="{Binding Name}" />
    </StackPanel>
</DataTemplate>
<DataTemplate x:Key="FirstDataTemplate">
    <StackPanel Margin="0,-6,0,0" Orientation="Horizontal">
        <HyperlinkButton x:Name="suspectname"
                         VerticalAlignment="Top"
                         Content="{Binding Name}" />
    </StackPanel>
</DataTemplate> 

Then we need to create a data template selector class which inherits from DataTemplateSelector class and override the SelectTemplateCore method to implement the logic. In the method, we can use ItemsControl.ItemsControlFromItemContainer method to get the ItemsControl and ItemsControl.IndexFromContainer method to get the index of the container then detect whether the item is the first item of the ItemsControl by comparing the index:

public class MyTemplateSelector : DataTemplateSelector
{
    public DataTemplate CommonTemplate { get; set; }
    public DataTemplate FirstTemplate { get; set; }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        var itemsControl = ItemsControl.ItemsControlFromItemContainer(container);
        if (itemsControl.IndexFromContainer(container) == 0)
        {
            return FirstTemplate;
        }
        return CommonTemplate;

    }
}

After this we can add MyTemplateSelector in Page.Resources like following:

<local:MyTemplateSelector x:Key="MyTemplateSelector"
                          CommonTemplate="{StaticResource CommonDataTemplate}"
                          FirstTemplate="{StaticResource FirstDataTemplate}" />

Then we can use it in ItemsControl:

<ItemsControl ItemTemplateSelector="{StaticResource MyTemplateSelector}" ItemsSource="{Binding }">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
查看更多
登录 后发表回答