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 にバインド します。

また、次の 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 にバインドする方法を示すコード/例/ドキュメントを誰かに教えてもらうことができるかもしれません不適切)。私のコレクションは、私がバインドしているものであることに注意してください。多くの例で、それらがサブプロパティにバインドされていることに気付きました。つまり、アルバムのコレクションを持ち、アルバムごとにそのプロパティ イメージにバインドする場合があります (参照: 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]を開くと、代わりにそのカードが表示されます。デバッガー情報を開くと効果があるのはなぜですか? デバッガーで両方のカードを開くとどうなるかという質問があるかもしれませんが、うまくいきません。操作タイムアウトの例外が発生します。おそらく私の画像ファイルは大きいと思います。10K バイトから 30K バイト。それが問題ですか?私はそうではないと推測していますが、それは画像の読み取りまたはバインディングに関する微妙な問題です。何が起こっている?ありがとう、デイブ

4

2 に答える 2

10

まず、ViewModel で Image コントロールを使用しないでください。ビューの DateTemplate には既に Image コントロールがあります。この Image コントロールのプロパティをバインドしたいのですがSource、このバインディングのソース プロパティを別の 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;
    }
}

または、 WPF に組み込まれたからstringへの自動変換があるため、単純にイメージ URI またはパス:ImageSource

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ます。

<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ようにプロパティ ゲッターで使用できます。

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

私は実際にあなたの問題を再現しようとはしませんでしたが、これで解決しない場合はそうします:

最初の xaml ブロッ​​クで、バインディングを混同したと思います。これは私が期待する方法であり、ItemsSource から ObservableCollection の画像、Image ソースから Image です。

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

2 番目のブロックでは、Source バインディングを完全に省略しました。

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