0

我正在尝试根据是否在项目绑定到的类中使用对象来更改绑定列表框中项目的选定状态,我似乎找不到这样做的方法,它必须保留动态的,因为对象可能会改变并因此在类的不同实例中使用:

  <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 的无效转换,有人知道我该怎么做吗?

4

1 回答 1

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 的元素,或者序列结束。如果找到元素,则返回 true,否则返回 false。

那么这一点:

storedInvestments
    .FirstOrDefault(i => i.attachedCards.Any(c => c.Id == activeCard.ID));

可以读作“给我第一个匹配的投资 i 在存储投资中,其中 i.attachedCards 包含卡 c ...”等等。

它查找storedInvestments序列中内部表达式返回 true 的第一个元素。如果它没有找到任何东西,它会返回类型的默认值(很可能是null,除非storedInvestments是 a struct)。

我不会继续讨论技术细节,但如果你真的对这一切的工作原理感兴趣,Jon Skeet 写了一系列关于它如何实际实现的精彩文章。强烈推荐。:)

于 2012-07-11T10:39:19.430 回答