8

我试图在 ListView 中显示一些图像并且没有成功。我正在使用 WPF MVVM,而 ListView 是简单地显示西装和排名数据的保留。(请参阅我以前的帖子:WPF 中的 MVVM - 如何提醒 ViewModel 模型发生变化......或者我应该吗?如果你有兴趣!)也就是说,我可以使用 ListView 以外的东西(如果这是建议的话)但我仍然想知道如何用 ListView 来做,假设它是可行的。我在 ViewModel 中绑定的属性是:

public ObservableCollection<Image> PlayerCardImages{
    get{
        ObservableCollection<Image> results = new ObservableCollection<Image>();
        foreach (CardModel card in PlayerCards)
        {
            Image img = new Image();
            BitmapImage bi3 = new BitmapImage();
            bi3.BeginInit();
            // TODO: Pick card based on suit/rank. Just get  1 image working now
            bi3.UriSource = new Uri("diamond-1.png", UriKind.Relative);
            bi3.EndInit();
            img.Stretch = Stretch.Fill;
            img.Source = bi3;            
            results.Add(img);
        }
        return results;
    }
}

在我使用的XAML代码中:

<Window.Resources>
 <DataTemplate x:Key="ImageCell">
        <StackPanel Orientation="Horizontal">
            <Image Source="{Binding PlayerCardImages}" Width="200" Height="200" Stretch="Fill" ToolTip="Add tooltip"/>
        </StackPanel>
    </DataTemplate>
</Window.Resources>

 <StackPanel Orientation="Vertical">
 <Label Content="Player Cards"/>
        <ListView  Name="lvwTitles" ItemsSource="{Binding}" 
 IsSynchronizedWithCurrentItem="True" 
 SelectionMode="Single" ItemTemplate="{StaticResource ImageCell}" Height="59">
        </ListView>
    </StackPanel>

这个想法被无耻地窃取了:WPF - 将图像水平绑定到 ListView 但是,它甚至没有出现数据绑定,正如我在 PlayerCardImages 中的断点没有被命中所证明的那样。

我还尝试了以下 XAML,但运气更好:

 <StackPanel Orientation="Vertical">
        <Label Content="Player Cards"/>
        <ListView

        AlternationCount="2"
        DataContext="{StaticResource PlayerCardsGroups }"
       ItemsSource="{Binding}"
        >
            <ListView.GroupStyle>
                <StaticResourceExtension 
                ResourceKey="CardGroupStyle"
                />
            </ListView.GroupStyle>
            <ListView.View>
                <GridView>
                    <GridViewColumn>
                <Image Height="50" Width="40"></Image>
                    </GridViewColumn>
                </GridView>                   
            </ListView.View>
        </ListView>
    </StackPanel>
    <Window.Resources>
    <CollectionViewSource x:Key="PlayerCardsGroups" 
        Source="{Binding Path=PlayerCardImages}">
    </CollectionViewSource>

    <GroupStyle x:Key="CardGroupStyle">
        <GroupStyle.HeaderTemplate>
            <DataTemplate>
                <TextBlock 
        x:Name="txt" 
        Background="{StaticResource Brush_HeaderBackground}"
        FontWeight="Bold"
        Foreground="White"
        Margin="1"
        Padding="4,2,0,2"
        Text="Cards" 
        />
            </DataTemplate>
        </GroupStyle.HeaderTemplate>
    </GroupStyle>

    <Style x:Key="CardItemStyle" TargetType="{x:Type ListViewItem}">
        <!-- 
  Stretch the content of each cell so that we can 
  right-align text in the Total Sales column. 
  -->
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <!-- 
  Bind the IsSelected property of a ListViewItem to the 
  IsSelected property of a CustomerViewModel object.
  -->
       <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="ItemsControl.AlternationIndex" Value="1" />
                    <Condition Property="IsSelected" Value="False" />
                    <Condition Property="IsMouseOver" Value="False" />
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="#EEEEEEEE" />
            </MultiTrigger>
        </Style.Triggers>
    </Style>

    </Window.Resources>

这段代码肯定会通过数据绑定——我的断点在程序开始时以及每当项目被添加到集合时被命中。但没有显示图像。与其用更多不起作用的 XAML 来折磨你,也许我可以请人指点我一些代码/示例/文档,这些代码/示例/文档显示如何将图像列表绑定到 ListView(或另一个控件,如果你真的觉得 ListView 是不当)。请注意,我的收藏是我绑定的东西。我注意到在许多示例中,它们都绑定到子属性。即他们可能有一个专辑的集合,并且对于每个专辑,他们绑定到它的属性图像(请参阅:在 WPF ListView 中将项目显示为图像)。

任何想法或帮助将不胜感激。

-戴夫

附加信息。

根据 Clemens 的建议,我现在有了 PlayerCardImages 的以下代码:

public ObservableCollection<ImageSource> PlayerCardImages
    {
        get
        {
            var results = new ObservableCollection<ImageSource>();

            //if (PlayerCards.Count == 0)
            //    return results;
            //else
            //{
            //    results.Add(new BitmapImage(new Uri(@"Images\\" + "diamond-1.png", UriKind.Relative)));
            //}
            foreach (var card in PlayerCards)
            {
                results.Add(new BitmapImage(new Uri(@"Images\\" + GetCardFileName(card), UriKind.Relative)));

            }
            return results;

        }

我使用了他建议的确切 XAML。它几乎可以工作。我说“几乎”是因为我注意到奇怪的行为,有时会显示 1 张卡,有时不会显示(我从未得到 2 张卡)。所有从文件和绑定中获取卡片似乎都在工作,我找到了我认为是最后一个错误的关键(这很奇怪)。如果在调试器中检查结果,并在调试器中进一步打开 results[0],我会显示该卡!实际上,我必须打开 [0](您会看到有关高度、宽度等的信息)才能使其正常工作。此外,如果我打开 [1],则会显示该卡。为什么打开调试器信息会有任何影响?对于那些可能会问的人,如果您在调试器中打开两张卡会发生什么......这是行不通的。我得到一个操作超时异常。我会说也许我的图像文件很大。10 KB 到 30 KB。那是问题吗?我猜不是,这是阅读图像或装订的一个微妙问题。到底是怎么回事?谢谢,戴夫

4

2 回答 2

10

首先,您不应该在 ViewModel 中使用 Image 控件。您的视图的 DateTemplate 中已经有一个 Image 控件。你要绑定Source这个Image控件的属性,这个绑定的源属性不能是另一个Image。

相反,您的 ViewModel 将使用ImageSource(或类似的派生类BitmapImage)作为图像类型,如下所示:

public ObservableCollection<ImageSource> PlayerCardImages
{
    get
    {
        var results = new ObservableCollection<ImageSource>();
        foreach (var card in PlayerCards)
        {
            results.Add(new BitmapImage(new Uri(card.ImageUrl)));
        }
        return results;
    }
}

或者只是图像 URI 或路径,因为 WPF 会自动转换stringImageSource内置的:

public ObservableCollection<string> PlayerCardImages
{
    get
    {
        var results = new ObservableCollection<string>();
        foreach (var card in PlayerCards)
        {
            results.Add(card.ImageUrl);
        }
        return results;
    }
}

您现在将 Listbox 的ItemsSource属性绑定到PlayerCardGames集合,并在 DataTemplate 中直接绑定到集合项。ListView 的 DataContext 必须设置为定义PlayerCardGames属性的对象的实例。

<ListView ItemsSource="{Binding PlayerCardGames}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Image Source="{Binding}" />
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

更新:由于加载图像文件似乎有问题,您可以尝试以下方法。它同步加载图像,您可以使用调试器单步执行。

public static ImageSource LoadImage(string fileName)
{
    var image = new BitmapImage();

    using (var stream = new FileStream(fileName, FileMode.Open))
    {
        image.BeginInit();
        image.CacheOption = BitmapCacheOption.OnLoad;
        image.StreamSource = stream;
        image.EndInit();
    }

    return image;
}

您可以在您的PlayerCardGames属性 getter 中使用此方法,如下所示:

foreach (var card in PlayerCards)
{
    results.Add(LoadImage(@"Images\\" + GetCardFileName(card)));
}
于 2013-03-24T16:49:10.520 回答
0

我并没有真正尝试重现您的问题,但如果这不能解决它,我会:

在您的第一个 xaml 块中,我认为您混淆了绑定。这就是我所期望的,ItemsSource 到图像的 ObservableCollection,图像源到图像。

<Image Source="{Binding}" ... />
<ListView  Name="lvwTitles" ItemsSource="{Binding PlayerCardImages}" ... />

在第二个块中,您完全省略了 Source 绑定:

<Image Source="{Binding}" Height="50" Width="40" />
于 2013-03-24T12:32:23.423 回答