使用数据绑定显示在ListView控件(或更好的东西!)图片在WPF MVVM [英] Displaying Images in ListView (or something better!) in WPF MVVM using databinding

查看:1439
本文介绍了使用数据绑定显示在ListView控件(或更好的东西!)图片在WPF MVVM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想显示在ListView一些图片,并没有成功。我使用WPF MVVM和ListView控件是从简单的显示西装和排名数据缓缴。 (见我的previous后:<一href=\"http://stackoverflow.com/questions/15439841/mvvm-in-wpf-how-to-alert-viewmodel-of-changes-in-model-or-should-i\">MVVM WPF中 - 如何提醒视图模型在模型的变化......或者我应该如果你有兴趣)这就是说,我可以用比其他的ListView东西(如果是这样的建议),但我还是想?!要知道如何与ListView的做到这一点,假设它是可行的。我的财产,我的视图模型绑定的是:

I am trying to display some images in a ListView and have not been successful. I am using WPF MVVM and the ListView is a holdover from simply displaying suits and rank data. (See my previous post: MVVM in WPF - How to alert ViewModel of changes in Model... or should I? if you are interested!) That is, I could use something other than ListView (if that is the advice) but I would still like to know how to do it with ListView, assuming it's doable. My property I'm binding to in the ViewModel is:

 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 code我使用的是:

In my XAML code I'm using:

<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证明。

This idea was shamelessly stolen from: WPF - bind images horizontally to ListView However, it doesn't even appear to databind as evidenced by my breakpoint in PlayerCardImages not being hit.

我也试过以下XAML与有些更好的运气:

I also tried the following XAML with somewhat better luck:

 <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>

这code绝对通过数据绑定老话 - 我的命中断点在程序的开始,每当项目添加到集合中。但不显示图像。而不是更多的XAML不工作折磨你,也许我可以请别人指出我的一些code /例子/文档,显示如何将图像列表绑定到ListView(或其他控件,如果你真的觉得该ListView控件是不恰当的)。请注意,我的收藏​​是我绑定到的东西。我注意到,有很多例子,它们绑定到子属性。即他们可能有相册的收集和他们绑定到它每一张专辑的财产图像(见:的显示在WPF的ListView 项目,如图像)。

this code definitely goes through databinding - my breakpoint is hit at the beginning of the program and whenever items are added to the collection. But no images is displayed. Rather than torture you with more XAML that does not work, perhaps I could ask someone to point me to some code/examples/docs that show how to bind a list of Images to a ListView (or another control if you really feel that ListView is inappropriate). Notice that my collection is the stuff I'm binding to. I notice that with many examples, they are binding to a subproperty. I.e. they may have a collection of albums and for each album they bind to it's property image (see: Showing items as images in a WPF ListView).

任何意见或帮助将非常AP preciated。

Any ideas or help would be much appreciated.

戴夫

附加信息。
基于克莱门斯的建议:我现在有这个code为PlayerCardImages:

Additional info. Based on suggestions by Clemens: I now have this code for 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张卡)。从文件,并结合所有获得卡似乎是工作,我找到了什么,我认为,关键是最后剩下的错误(和它的奇妙)。如果在调试器,我检查结果,并进一步开拓的结果[0]在调试器中,我得到了显示卡!其实我有开拓[0](你看到的高度,宽度等信息),这个工作。此外,如果我开[1],我拿到卡时,显示来代替。为什么会打开调试器的信息有什么影响?对于那些你谁可能会问,如果你在调试器...还是不行开拓两张卡会发生什么。我得到一个操作超时异常。我会说,也许我的图像文件都大。 10Kbytes为30 KB。那是什么问题?我猜没有,那它与读取图像或绑定一个微妙的问题。到底是怎么回事?谢谢,戴夫

I used the exact XAML he suggested. It almost works. I say "almost" because I noticed strange behavior whereby sometimes 1 card would show and sometimes not (I never got 2 cards). All the getting cards from files and binding seems to be working and I tracked down what I think is key to the last remaining bug (and it's BIZARRE). If in the debugger, I examine results, and further open up results[0] in the debugger, I get that card displayed! I actually have to open up [0] (you see info about height, width, etc.) for this to work. Furthermore if I open up [1], I get that card displayed instead. Why would opening up the debugger info have any effect? For those of you who might ask, what happens if you open up both cards in the debugger... that doesn't work. I get a operation timed out exception. I will say that perhaps my image files are big. 10Kbytes to 30 Kbytes. Is that the problem? I'm guessing not, and that it's a subtle problem with reading in the images or binding. What is going on? Thanks, Dave

推荐答案

首先,你不应该使用的图像控制在你的视图模型。你已经在你的视图的DateTemplate Image控件。你想这个图像conntrol的来源属性,这种结合不能是另一个图像源属性绑定。

First, you should not use Image controls in your ViewModel. You already have an Image control in the DateTemplate of your view. You want to bind the Source property of this Image conntrol, and the source property of this binding can't be another Image.

而不是你的ViewModel要么使用<一个href=\"http://msdn.microsoft.com/en-us/library/system.windows.media.imagesource.aspx\"><$c$c>ImageSource (或派生类像<一个href=\"http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmapimage.aspx\"><$c$c>BitmapImage)作为图像类型,就像这样:

Instead your ViewModel would either use ImageSource (or a derived class like BitmapImage) as image type, like this:

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或路径,因为从字符串自动转换为的ImageSource 内置WPF

Or simply the image URIs or paths, as there is an automatic conversion from string to ImageSource built into WPF:

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

您会立即绑定列表框的的ItemsSource 属性设置为 PlayerCardGames 集合,在DataTemplate中直接绑定到收集项目。 ListView的DataContext的已被设置为定义了 PlayerCardGames 属性的对象的实例。

You would now bind your Listbox's ItemsSource property to the PlayerCardGames collection, and in the DataTemplate you bind directly to the collection item. The ListView's DataContext has to be set to an instance of the object that defines the PlayerCardGames property.

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


更新:由于有似乎是加载图像文件的问题,你可以试试下面的方法。它同步加载图像,你可以使用调试器来逐步通过。


UPDATE: As there seems to be a problem with loading the image files, you may try the following method. It loads images synchronously and you are able to step through with the debugger.

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这样此方法:

You can use this method in your PlayerCardGames property getter like this:

foreach (var card in PlayerCards)
{
    results.Add(LoadImage(@"Images\\" + GetCardFileName(card)));
}

这篇关于使用数据绑定显示在ListView控件(或更好的东西!)图片在WPF MVVM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆