我正在尝试根据项目绑定的类中是否使用对象来更改绑定列表框中项目的选定状态,我似乎无法找到执行此操作的方法必须保持动态,因为对象可能会更改,因此在类的不同实例中使用:
<Popup x:Name="ContextMenuPopup" Height="250" Width="300" Margin="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Canvas Name="popupholder" Background="DarkSeaGreen" Height="250" Width="300" HorizontalAlignment="Center">
<StackPanel Orientation="Vertical">
<TextBlock Name="popupTitle" Text="Select Investments" Margin="20,0,0,0" FontFamily="Courier New" FontSize="22" HorizontalAlignment="Center" Foreground="Black" />
<ListBox x:Name="investPicker" SelectionChanged="ListBox_SelectionChanged" LayoutUpdated="investPicker_LayoutUpdated" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="10,20,0,0" SelectionMode="Multiple">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Width="100"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Name="executeSelection" Content="Ok" Click="executeSelection_Click" Margin="40,5,0,0" VerticalAlignment="Bottom"/>
</StackPanel>
</Canvas>
</Popup>
我们背后的代码是:
private void ApplicationBarIconButton_Click_1(object sender, EventArgs e)
{
this.investPicker.ItemsSource = storedInvestments;
foreach (Investment investment in investPicker.Items)
{
foreach (CardDataSet card in investment.attachedCards)
if (card.ID == activeCard.ID)
VisualStateManager.GoToState((ListBoxItem) investPicker.Items[investment.ID -1], "Selected", true);
}
ContextMenuPopup.IsOpen = true;
}
现在显然代码不能作为从我的类到ListBoxItem的无效强制转换,任何人都知道如何做到这一点?
答案 0 :(得分:1)
看起来你只有一个选定的项目,那么如何:
investPicker.SelectedItem = storedInvestments
.FirstOrDefault(i => i.attachedCards.Any(c => c.Id == activeCard.ID));
或者,如果你有多个:
var matchingItems = storedInvestments
.Where(i => i.attachedCards.Any(c => c.Id == activeCard.ID));
foreach (var i in matchingItems)
investPicker.SelectedItems.Add(i);
[编辑]
OP不知道箭头操作符=>
的含义,所以让我们澄清一下。它被称为 lambda表达式,出于本讨论的目的,您可以将其视为一种小型的内联方法。
这个表达式:
i.attachedCards.Any(c => c.Id == activeCard.ID);
可以读作“i.attachedCards包含c.Id等于activeCard.ID的任何卡片c。”
表示c => c.Id == activeCard.ID
的位表示一种方法,也可以写成:
static bool IsActiveCard(Card c) { return c.Id == activeCard.ID; }
事实上,如果您这样写,可以将表达式更改为:
i.attachedCards.Any(IsActiveCard);
表达式的其余部分是对IEnumerable<T>
扩展方法Any
的调用,该方法为attachedCards
序列中的每个元素计算方法,直到找到方法返回的元素为止是,或者序列结束。如果它找到一个元素,则返回true;如果没有,则返回false。
这一点:
storedInvestments
.FirstOrDefault(i => i.attachedCards.Any(c => c.Id == activeCard.ID));
可以理解为“给我第一个匹配的投资i in storedInvestments,其中i.attachedCards包含一张卡片......”等等。
它查找storedInvestments
序列中内部表达式返回true的第一个元素。如果找不到任何内容,则会返回该类型的默认值(可能为null
,除非storedInvestments
为struct
)。
我不会继续谈论技术细节,但如果你真的对这一切是如何运作感兴趣的话,Jon Skeet已经写了一篇很棒的series of articles关于它是如何实际实现的。强烈推荐。 :)