2

I have a ItemsControlwhich have bound items. As you can see in the screenshot, those items are bound to a property and I want an extra item appear which will have totally different behaviour than the other items. How can I achieve this (preferabelly with xaml only)?

Screenshot for what I want

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Dester Dezzods
  • 1,417
  • 4
  • 17
  • 33
  • Are you using a MVVM architecture in your application? Anyway, there is no way to do that only in XAML since this is not View-related, but Model-related. The separation of concern dictates that this should be handled by a command in your ViewModel. – gretro Apr 02 '16 at 21:59
  • @DesterDezzods there is `CompositeCollection` but it is tricky to use when you bind `ItemsSource` to list in view model. Easiest solution would be to have collection of your items and some item of different type at the end and have 2 `DataTemplate` in `ItemsControl.Resources`, one for each `DataType` – dkozl Apr 02 '16 at 22:01
  • @dkozl, I didn't know you could have 2 datasource I'll see what I can find. thanks :) – Dester Dezzods Apr 02 '16 at 22:17
  • One items source with two types and two data templates – dkozl Apr 02 '16 at 22:24

2 Answers2

6

Take a look at Composite Collection. Wpf example here or here.

Based on comment, here is sample code from first example

<ComboBox>
    <ComboBox.ItemsSource>
        <CompositeCollection>
            <ComboBoxItem Content="All" />
            <CollectionContainer Collection="{Binding Source={StaticResource AllBitsSource}}" />
        </CompositeCollection>
    </ComboBox.ItemsSource>
</ComboBox>

Edit - MVVM

The issue with CollectionContainer is that is does not have access to curent DataContext. StaticResource solves it

xaml

<Window x:Class="WpfApplication5.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:WpfApplication5"
        Title="MainWindow" Height="300" Width="525" FontSize="25">

    <StackPanel Name="stk">
        <StackPanel.Resources>
            <CollectionViewSource x:Key="cvsBooks" Source="{Binding Path=Books}" />
        </StackPanel.Resources>

        <ListBox>
            <ListBox.ItemsSource>
                <CompositeCollection>
                    <ListBoxItem>
                        <StackPanel>
                            <TextBlock Margin="5,0">Not tagged</TextBlock>
                        </StackPanel>
                    </ListBoxItem>
                    <CollectionContainer Collection="{Binding Source={StaticResource cvsBooks}}"/>
                </CompositeCollection>
            </ListBox.ItemsSource>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <Button Content="Add" Click="Button_Click"/>
    </StackPanel>
</Window>

C#

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var vm = new ViewModel();
        this.stk.DataContext = vm;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        //should be Command in MVVM, but this is just example to see that ObservableCollection works
        var btn = sender as Button;
        (btn.DataContext as ViewModel).Books.Add(new Book() { Name = "Book" + DateTime.Now.Second });
    }

}

public class ViewModel
{
    public ViewModel()
    {
        this.Books = new ObservableCollection<Book>();
        this.Books.Add(new Book() { Name = "Book 1" });
        this.Books.Add(new Book() { Name = "Book 2" });
        this.Books.Add(new Book() { Name = "Book 3" });
    }

    public ObservableCollection<Book> Books { get; private set; }
}

public class Book
{
    public string Name { get; set; }
}
Community
  • 1
  • 1
kurin123
  • 363
  • 1
  • 6
0

which will have totally different behaviour than the other items.

Behavior is done with styles. I will provide a listbox example which is translatable to the ItemsControl.


Say for example we have an Order class with these properties

public class Order
{
    public string CustomerName { get; set; }
    public int OrderId { get; set; }
    public bool InProgress { get; set; }
}

When an order is marked as in progress (InProgress = true) we want to show red in our list box say for "Alpha" and "Omega" which are in progress:

enter image description here

ListBox Xaml

Here is the Xaml which binds to our data (how you bind is up to you) and shows how to work with Style(s), DataTemplate, and DataTrigger(s) to achieve that:

<ListBox ItemsSource="{StaticResource Orders}"
         x:Name="lbOrders">
    <ListBox.Resources>
        <DataTemplate DataType="{x:Type model:Order}">
            <TextBlock Text="{Binding Path=CustomerName}" />
        </DataTemplate>
        <Style TargetType="{x:Type ListBoxItem}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=InProgress}"
                             Value="True">
                    <Setter Property="Foreground"
                            Value="Red" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.Resources>
</ListBox>

Here is the data setup in the pages's resource Xaml to do that, but it could be created in code behind:

<Window.Resources>
    <model:Orders x:Key="Orders">
        <model:Order CustomerName="Alpha"
                        OrderId="997"
                        InProgress="True" />
        <model:Order CustomerName="Beta"
                        OrderId="998"
                        InProgress="False" />
        <model:Order CustomerName="Omega"
                        OrderId="999"
                        InProgress="True" />
        <model:Order CustomerName="Zeta"
                        OrderId="1000"
                        InProgress="False" />
    </model:Orders>
</Window.Resources>

Now its just a question of what property your added item will have which will trigger a different style.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122