Reputation: 1535
I have a ItemsControl
which 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)?
Upvotes: 2
Views: 2253
Reputation: 363
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; }
}
Upvotes: 6
Reputation: 31606
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:
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.
Upvotes: 0