wpf 如何将 CollectionContainer 绑定到视图模型中的集合?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6446699/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you bind a CollectionContainer to a collection in a view model?
提问by Frinavale
I have a view model with a property that exposes a collection of things. I have a ComboBox whose ItemsSource property is bound to this collection. Now the user can select from the list.
我有一个具有公开事物集合的属性的视图模型。我有一个 ComboBox,其 ItemsSource 属性绑定到此集合。现在用户可以从列表中进行选择。
I want to allow the user to clear the selection, so I want to add an item (that is Null) to ComboBox. It's pretty straightforward.
我想让用户清除选择,所以我想向 ComboBox 添加一个项目(即 Null)。这很简单。
I decided to try and use a CompositeCollection for the ItemsSource so that I could add the items in the existing list to the ComboBox as well as the extra Null item.
我决定尝试为 ItemsSource 使用 CompositeCollection,以便我可以将现有列表中的项目以及额外的 Null 项目添加到 ComboBox。
After fighting with this for a while I decided to return to the documentation on the CompositeCollection Class. I copied their example and the modified it to use a view model instead of Static Resources.
在与此斗争了一段时间后,我决定返回到关于CompositeCollection Class的文档。我复制了他们的示例并将其修改为使用视图模型而不是静态资源。
I discovered that no items show up in the list when I bind the CollectionContainer to the list exposed by the ViewModel.
当我将 CollectionContainer 绑定到 ViewModel 公开的列表时,我发现列表中没有显示任何项目。
I'm not sure how to get around this problem and I'm looking for any advice on this topic.
我不确定如何解决这个问题,我正在寻找有关此主题的任何建议。
Here is my XAML code:
这是我的 XAML 代码:
<Window Background="CornflowerBlue" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:c="clr-namespace:TryingWPF" x:Class="CompositeCollections" Title="CompositeCollections" SizeToContent="WidthAndHeight">
<Window.Resources>
<c:CompositeCollectionVM x:Key="CompositeCollectionVM"/>
<XmlDataProvider x:Key="GreekHeroesData" XPath="GreekHeroes/Hero">
<x:XData>
<GreekHeroes xmlns="">
<Hero Name="Jason" />
<Hero Name="Hercules" />
<Hero Name="Bellerophon" />
<Hero Name="Theseus" />
<Hero Name="Odysseus" />
<Hero Name="Perseus" />
</GreekHeroes>
</x:XData>
</XmlDataProvider>
<DataTemplate DataType="{x:Type c:GreekGod}">
<TextBlock Text="{Binding Path=Name}" Foreground="Gold"/>
</DataTemplate>
<DataTemplate DataType="Hero">
<TextBlock Text="{Binding XPath=@Name}" Foreground="Cyan"/>
</DataTemplate>
</Window.Resources>
<StackPanel DataContext="{StaticResource CompositeCollectionVM}">
<TextBlock FontSize="18" FontWeight="Bold" Margin="10" HorizontalAlignment="Center" Foreground="WhiteSmoke">Trying Composite Collections</TextBlock>
<DockPanel>
<ListBox Name="myListBox" Height="300" Background="#99333333">
<ListBox.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding GreekGods}" />
<CollectionContainer Collection="{Binding Source={StaticResource GreekHeroesData}}" />
<ListBoxItem Foreground="Magenta">Other Listbox Item 1</ListBoxItem>
<ListBoxItem Foreground="Magenta">Other Listbox Item 2</ListBoxItem>
</CompositeCollection>
</ListBox.ItemsSource>
</ListBox>
<ListBox ItemsSource="{Binding GreekGods}" Background="#99333333" Margin="5,0" HorizontalAlignment="Right">
</ListBox>
</DockPanel>
</StackPanel>
</Window>
(As you can see when I bind the ItemsSource of the second ListBox to the list property...the items show up)
(如您所见,当我将第二个 ListBox 的 ItemsSource 绑定到列表属性时……项目显示出来)
And here is my VB.NET code that makes the XAML code work:
这是我的 VB.NET 代码,它使 XAML 代码工作:
Public Class CompositeCollections
End Class
Public Class GreekGod
Public Property GreekName
Public Property Name
Public Property Description
Public Sub New(ByVal greekName As String, ByVal englishName As String, ByVal description As String)
Me.GreekName = greekName
Me.Name = englishName
Me.Description = description
End Sub
End Class
Public Class CompositeCollectionVM
Public Property GreekGods As System.Collections.ObjectModel.ObservableCollection(Of GreekGod)
Public Sub New()
GreekGods = New System.Collections.ObjectModel.ObservableCollection(Of GreekGod)
GreekGods.Add(New GreekGod("?φροδ?τη (Venus)", "Aphrodite", "Goddess of love and beauty. Although married to Hephaestus she had many lovers, most notably Ares. She was depicted as a beautiful woman usually accompanied by her son Eros. Her symbols include the rose, scallop shell, and myrtle wreath. Her sacred animal is the dove."))
GreekGods.Add(New GreekGod("?π?λλων (Apóllō)", "Apollo", "God of music, healing, plague, prophecies, poetry, and archery; associated with light, truth and the sun. He is Artemis's twin brother and Hermes elder brother, and son of Zeus and Leto. He was depicted as a handsome, beardless youth with long hair and various attributes including a laurel wreath, bow and quiver, raven, and lyre. Apollo's sacred animal are red cattle."))
GreekGods.Add(New GreekGod("?ρη? (Mars)", "Ares", "God of war, bloodlust, violence, manly courage, and civil order. The son of Zeus and Hera, he was depicted as either a mature, bearded warrior dressed in battle arms, or a nude beardless youth with helm and spear. His attributes are golden armour and a bronze-tipped spear. His sacred animals are the vulture, venomous snakes, alligators, and dogs."))
GreekGods.Add(New GreekGod("?ρτεμι? (Diana)", "Artemis", "Virgin goddess of the hunt, wilderness, wild animals, childbirth and plague. In later times she became associated with the moon. She is the daughter of Zeus and Leto, and twin sister of Apollo. In art she was usually depicted as a young woman dressed in a short knee-length chiton and equipped with a hunting bow and a quiver of arrows. In addition to the bow, her attributes include hunting spears, animal pelts, deer and other wild animals. Her sacred animals are deer, bears, and wild boars."))
GreekGods.Add(New GreekGod("?θην? (Minerva)", "Athena", "Goddess of wisdom, warfare, battle strategy, heroic endeavour, handicrafts and reason. According to most traditions she was born from Zeus's head. She was depicted crowned with a crested helm, armed with shield (Aegis), which holds medusa's head to paralyze her enemies who looked at it and a spear. Her symbols include the aegis and the olive tree. She is commonly shown accompanied by her sacred animal, the snowy owl."))
GreekGods.Add(New GreekGod("Δημ?τηρ (Ceres)", "Demeter", "Goddess of agriculture, horticulture, grain and harvest. Demeter is a daughter of Cronus and Rhea and sister of Zeus, by whom she bore Persephone. She was depicted as a mature woman, often crowned and holding sheafs of wheat and a torch. Her symbols are the Cornucopia (horn of plenty), wheat-ears, the winged serpent and the lotus staff. Her sacred animals are pigs and snakes."))
GreekGods.Add(New GreekGod("Δι?νυσο? (Bacchus)", "Dionysos", "God of wine, parties and festivals, madness, civilization, drunkenness and pleasure at forever young. He was depicted in art as either an older bearded god or a pretty effeminate, long-haired youth. His attributes include the thyrsus (a pinecone-tipped staff), drinking cup, grape vine, and a crown of ivy. Animals sacred to him include dolphins, serpents, tigers, panthers, and donkeys. A later addition to the Olympians, in some accounts he replaced Hestia."))
GreekGods.Add(New GreekGod("?δη? (Hádēs) or Πλο?των (Ploútón)", "Hades or Pluto", "King of the Underworld and god of the dead and the hidden wealth of the Earth. His consort is Persephone and his attributes are the key of Hades, the Helm of Darkness, and the three-headed dog, Cerberus. The screech owl was sacred to him. Despite being the son of Cronus and Rhea and the elder brother of Zeus, as a chthonic god he is only rarely listed among the Olympians. The name Pluto became more common in the Classical period with the mystery religions and Athenian literature."))
GreekGods.Add(New GreekGod("?φαιστο? (H?phaistos)", "Hephaestus or Vulcan", "Crippled god of fire, metalworking, stonemasonry, sculpture and volcanism. The son of Hera alone, he is the smith of the gods and the husband of the adulterous Aphrodite. He was usually depicted as a bearded man holding hammer and tongs—the tools of a smith—and riding a donkey. His symbols are the hammer, tongs, and anvil. His sacred animals are the donkey, the guard dog and the crane. When he was born, he was thrown off of Mount Olympus by Hera as he was considered ugly."))
GreekGods.Add(New GreekGod("?ρα (Juno)", "Hera", "Queen of marriage, women, childbirth, heirs, kings and empires. She is daughter of Cronus and Rhea. She was usually depicted as a beautiful woman wearing a crown and veil and holding a royal, lotus-tipped staff. Her sacred animals are the cow, the peacock. She is the eternal wife of Zeus."))
GreekGods.Add(New GreekGod("?ρμ?? (Mercury)", "Hermes", "God of travel, messengers, trade, thievery, cunning wiles, language, writing, diplomacy, athletics, and animal husbandry. He is the messenger of the gods, a psychopomp who leads the souls of the dead into Hades' realm, and the son of Zeus and Maia. He was depicted either as a handsome and athletic beardless youth, or as an older bearded man. His attributes include the herald's wand or caduceus, winged sandals, and a traveler's cap. His sacred animals are the tortoise, the ram, and the hawk."))
GreekGods.Add(New GreekGod("?στ?α (Vesta)", "Hestia", "Virgin goddess of the hearth, home and cooking. She is a daughter of Rhea and Cronus and sister of Zeus. She was depicted as a modestly veiled woman, whose symbols are the hearth and kettle. In some accounts, she gave up her seat as one of the Twelve Olympians to tend to the sacred flame on Mount Olympus for Dionysus."))
GreekGods.Add(New GreekGod("Ποσειδ?ν (Neptune)", "Poseidon", "God of the sea, rivers, floods, droughts, storms, earthquakes, and the creator of horses; known as the 'Earth Shaker' or 'Storm Bringer'. He is a son of Cronus and Rhea and brother to Zeus and Hades. In classical artwork, he was depicted as a mature man of sturdy build with a dark beard, and holding a trident. The horse and the dolphin are sacred to him."))
GreekGods.Add(New GreekGod("Ζε?? (Jupiter)", "Zeus", "The king of the gods, the ruler of Mount Olympus and the god of the sky, weather, thunder, law, order, and fate. He is the youngest son of Cronus and Rhea, whom he overthrew after Cronus swallowed his brothers and sisters and he is brother-husband to Hera. In artwork, he was depicted as a regal, mature man with a sturdy figure and dark beard. His usual attributes are the royal sceptre and the lightning bolt. His main attribute was his master bolt. His sacred animals are the eagle and the bull."))
End Sub
End Class
Thanks for your help!
谢谢你的帮助!
EDIT:
编辑:
H.B.'s answer worked perfectly. Here is the updated working XAML:
HB的回答完美无缺。这是更新后的工作 XAML:
<Window Background="CornflowerBlue"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:TryingWPF"
x:Class="CompositeCollections"
Title="CompositeCollections"
SizeToContent="WidthAndHeight">
<Window.Resources>
<c:CompositeCollectionVM x:Key="CompositeCollectionVM"/>
<XmlDataProvider x:Key="GreekHeroesData" XPath="GreekHeroes/Hero">
<x:XData>
<GreekHeroes xmlns="">
<Hero Name="Jason" />
<Hero Name="Hercules" />
<Hero Name="Bellerophon" />
<Hero Name="Theseus" />
<Hero Name="Odysseus" />
<Hero Name="Perseus" />
</GreekHeroes>
</x:XData>
</XmlDataProvider>
<DataTemplate DataType="{x:Type c:GreekGod}">
<TextBlock Text="{Binding Path=Name}" Foreground="Gold"/>
</DataTemplate>
<DataTemplate DataType="Hero">
<TextBlock Text="{Binding XPath=@Name}" Foreground="Cyan"/>
</DataTemplate>
</Window.Resources>
<StackPanel x:Name="myStackPanel" DataContext="{StaticResource CompositeCollectionVM}">
<StackPanel.Resources>
<CompositeCollection x:Key="compCollection">
<CollectionContainer Collection="{Binding DataContext.GreekGods, Source={x:Reference myStackPanel}}" />
<CollectionContainer Collection="{Binding Source={StaticResource GreekHeroesData}}" />
<ListBoxItem Foreground="Magenta">Other Listbox Item 1</ListBoxItem>
<ListBoxItem Foreground="Magenta">Other Listbox Item 2</ListBoxItem>
</CompositeCollection>
</StackPanel.Resources>
<TextBlock FontSize="18" FontWeight="Bold" Margin="10" HorizontalAlignment="Center" Foreground="WhiteSmoke">Trying Composite Collections</TextBlock>
<DockPanel>
<ListBox Name="compositeListBox" ItemsSource="{Binding Source={StaticResource compCollection}}" Height="300" Background="#99333333" >
</ListBox>
<ListBox Name="greekGodsListBox" ItemsSource="{Binding GreekGods}" Background="#99333333" Margin="5,0" HorizontalAlignment="Right">
</ListBox>
</DockPanel>
</StackPanel>
</Window>
回答by H.B.
The CompositeCollection
has no DataContext
, the bindings in the CollectionContainers
will not work if they bind directly to a property (which implicitly uses the DataContext
as source).
在CompositeCollection
没有DataContext
在绑定CollectionContainers
,如果他们直接绑定到一个属性(隐式使用将无法正常工作DataContext
的源)。
You need to explicitly specify a source, i would suggest you name the control with your DataContext
and use x:Reference
to get it (ElementName
will notwork) or you use a StaticResource
, e.g.
您需要明确指定一个来源,我建议你的名字与你的控制DataContext
和使用x:Reference
得到它(ElementName
将不工作),或者你使用StaticResource
,如
<CollectionContainer Collection="{Binding DataContext.GreekGods, Source={x:Reference myStackPanel}}"/>
<CollectionContainer Collection="{Binding GreekGods, Source={StaticResource CompositeCollectionVM}}"/>
Note that when using x:Reference
the compiler easily trips you up with cyclical dependency errors, to avoid those place your CompositeCollection
in the resources of the control you reference, then insert it wherever it belongs using the StaticResource
markup extension.
请注意,当使用x:Reference
编译器时,您很容易遇到循环依赖错误,以避免将您CompositeCollection
放在您引用的控件资源中,然后使用StaticResource
标记扩展将其插入到它所属的任何位置。
回答by Johan Larsson
An IMultiValueConverter
is a nice fit for CompositeCollection
but not for your specific case where you add stuff in xaml.
AnIMultiValueConverter
非常适合CompositeCollection
但不适合您在 xaml 中添加内容的特定情况。
Converter:
转换器:
using System;
using System.Collections;
using System.Globalization;
using System.Windows.Data;
public class CompositeCollectionConverter : IMultiValueConverter
{
public static readonly CompositeCollectionConverter Default = new CompositeCollectionConverter();
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var compositeCollection = new CompositeCollection();
foreach (var value in values)
{
var enumerable = value as IEnumerable;
if (enumerable != null)
{
compositeCollection.Add(new CollectionContainer { Collection = enumerable });
}
else
{
compositeCollection.Add(value);
}
}
return compositeCollection;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException("CompositeCollectionConverter ony supports oneway bindings");
}
}
Usage:
用法:
<ListBox>
<ListBox.ItemsSource>
<MultiBinding Converter="{x:Static local:CompositeCollectionConverter.Default}">
<Binding Path="Col1" />
<Binding Path="Col2" />
...
</MultiBinding>
</ListBox.ItemsSource>
...
</ListBox>