locked
silverlight で読み込んだ画像を並べて表示する RRS feed

  • 質問

  • silverlight で読み込んだ複数の画像を並べて表示するする方法を教えてください。

    画像はならべるときに、適度の間を開けることと、読み込んだサイズの異なる画像を同一のサイズにして並べることを想定してます。

    一枚の画像を表示させるとこまでは出来ています。

    2011年1月2日 5:22

回答

  • takahashi32 さんこんばんは、おのでらです。

    複数の画像を並べるのであれば一般的には「ListBox」を使う方法がオーソドックスかと思います。

    以下のかずきさんのブログでは WPF で作成されていますがほとんどそのまま Silverlight で流用することができます。

    ものすごく簡単に書けば下のような感じで出来上がると思います。あとは自分のアプリケーションに合わせて作り直してみてください。

    ◆XAML (MainPage.xaml)

    <Grid x:Name="LayoutRoot" Background="White">
     <ListBox ItemsSource="{Binding Items}">
      <ListBox.ItemTemplate>
       <DataTemplate>
        <Image Margin="5" Width="100" Height="100" Source="{Binding Path}" />
       </DataTemplate>
      </ListBox.ItemTemplate>
     </ListBox>
    </Grid>
    
    

    ◆コード (MainPage.xaml.cs) (※面倒なので全部コードビハインド側に書いています)

    public partial class MainPage : UserControl
    {
     public class Item
     {
      public string Path { get; set; }
     }
     public class ViewModel
     {
      private ObservableCollection<Item> bb = new ObservableCollection<Item>();
      public ObservableCollection<Item> Items
      {
       get { return this.bb; }
       set { this.bb = value; }
      }
     }
     public MainPage()
     {
      InitializeComponent();
      ViewModel viewModel = new ViewModel();
      viewModel.Items.Add(new Item() { Path = "どっかの画像URL1", });
      viewModel.Items.Add(new Item() { Path = "どっかの画像URL2", });
      viewModel.Items.Add(new Item() { Path = "どっかの画像URL3", });
      viewModel.Items.Add(new Item() { Path = "どっかの画像URL4", });
      this.DataContext = viewModel;
     }
    }
    
    • 回答としてマーク Shingo Tada 2011年1月3日 13:51
    2011年1月2日 13:19
  •  前に提示したサンプルは string で定義しているので実行時に指定された URI からイメージを取得しに行って作成するようになっています。この部分を「ImageSource」でバインドするようにしてみてください。

     ※バインドやビューモデル、ビューへの通知の仕組みなどの説明は端折ってますのでわからない場合は適時調べてください(^^;)

     私のサンプルと takahashi32 のコードを組み合わせた感じだと下のようなコードで実現できると思います。変更点はコメントで書いています。

    ◆XAML (MainPage.xaml)

    <Grid x:Name="LayoutRoot" Background="White">
     <Grid.RowDefinitions>
      <RowDefinition Height="120" />
      <RowDefinition Height="30" />
      <RowDefinition Height="*" />
     </Grid.RowDefinitions>
     <!-- ドロップエリア -->
     <Border x:Name="border1" BorderBrush="Silver" BorderThickness="1" Height="100" HorizontalAlignment="Left" Margin="12,12,0,0" VerticalAlignment="Top" Width="376" Background="#FFB19C9C" AllowDrop="True" Drop="DropHere" UseLayoutRounding="True">
      <TextBlock TextWrapping="Wrap" Text="Drop Files Here." HorizontalAlignment="Center" VerticalAlignment="Center" />
     </Border>
     <!-- 一応こんな感じに定義していたものと想定して Image を記述 -->
     <Image Grid.Row="1" x:Name="image1"></Image>
     <!-- ListBox -->
     <ListBox Grid.Row="2" ItemsSource="{Binding Items}">
      <ListBox.ItemTemplate>
       <DataTemplate>
        <!-- バインドするプロパティ名を Path から Image に変更 (名前は一致すればなんでもいいです) -->
        <Image Margin="5" Width="100" Height="100" Source="{Binding Image}" />
       </DataTemplate>
      </ListBox.ItemTemplate>
     </ListBox>
    </Grid>
    

    ◆コード (MainPage.xaml.cs)

    public partial class MainPage : UserControl
    {
     private ViewModel viewModel; // バインドしているインスタンスを使うので保持する形に
     public class Item
     {
      public ImageSource Image { get; set; } // string Path → ImageSource Image に変更
     }
     public class ViewModel
     {
      private ObservableCollection<Item> _items = new ObservableCollection<Item>();
      public ObservableCollection<Item> Items
      {
       get { return this._items; }
       set { this._items = value; }
      }
     }
     public MainPage()
     {
      InitializeComponent();
      this.viewModel = new ViewModel(); // フィールドに持つ
      this.DataContext = viewModel; // ビューにバインド
     }
     private void DropHere(object sender, DragEventArgs e)
     {
      IDataObject data = e.Data;
      if (data.GetDataPresent(DataFormats.FileDrop))
      {
       FileInfo[] files = data.GetData(DataFormats.FileDrop) as FileInfo[];
       foreach (var file in files)
       {
        switch (file.Extension)
        {
         case ".png":
         case ".jpg":
          FileStream fs = file.OpenRead();
          BitmapImage bmp = new BitmapImage();
          bmp.SetSource(fs);
          //image1.Source = bmp; //イメージタグに画像を指定
          // 作成したイメージをビューにバインドしているアイテム一覧に追加
          // ※ ObservableCollection 使ってるのでそのままビューに変更が通知されます
          this.viewModel.Items.Add(new Item() { Image = bmp, });
          break;
        }
       }
      }
     }
    }
    

    おのでら / ソーサリーフォース(http://sorceryforce.com/)
    • 回答としてマーク Shingo Tada 2011年1月4日 6:33
    2011年1月3日 15:16

すべての返信

  • takahashi32 さんこんばんは、おのでらです。

    複数の画像を並べるのであれば一般的には「ListBox」を使う方法がオーソドックスかと思います。

    以下のかずきさんのブログでは WPF で作成されていますがほとんどそのまま Silverlight で流用することができます。

    ものすごく簡単に書けば下のような感じで出来上がると思います。あとは自分のアプリケーションに合わせて作り直してみてください。

    ◆XAML (MainPage.xaml)

    <Grid x:Name="LayoutRoot" Background="White">
     <ListBox ItemsSource="{Binding Items}">
      <ListBox.ItemTemplate>
       <DataTemplate>
        <Image Margin="5" Width="100" Height="100" Source="{Binding Path}" />
       </DataTemplate>
      </ListBox.ItemTemplate>
     </ListBox>
    </Grid>
    
    

    ◆コード (MainPage.xaml.cs) (※面倒なので全部コードビハインド側に書いています)

    public partial class MainPage : UserControl
    {
     public class Item
     {
      public string Path { get; set; }
     }
     public class ViewModel
     {
      private ObservableCollection<Item> bb = new ObservableCollection<Item>();
      public ObservableCollection<Item> Items
      {
       get { return this.bb; }
       set { this.bb = value; }
      }
     }
     public MainPage()
     {
      InitializeComponent();
      ViewModel viewModel = new ViewModel();
      viewModel.Items.Add(new Item() { Path = "どっかの画像URL1", });
      viewModel.Items.Add(new Item() { Path = "どっかの画像URL2", });
      viewModel.Items.Add(new Item() { Path = "どっかの画像URL3", });
      viewModel.Items.Add(new Item() { Path = "どっかの画像URL4", });
      this.DataContext = viewModel;
     }
    }
    
    • 回答としてマーク Shingo Tada 2011年1月3日 13:51
    2011年1月2日 13:19
  • ご返信ありがとうございます!大変参考になりました。

    この通りやってうまくいきました。かずきさんのブログ、私も良く拝見してます。

     

    あと、すみません。もう少し質問させてください。

    上のサンプルコードでは Path に string で URL を渡しているのですが、目的としてはここに BitmapImage を渡そうと思ってます。いろいろと試してみたんですが、BitpmapImage で渡そうとすると上のサンプルコードで記載していただいたやり方が使えません。

    (border 内にドラッグ & ドロップした画像ファイルを ListBox に並べて表示されることを想定してます。)

    今書いてるコードはこんな感じです。質問ばかりで申し訳ございません。。。

     

        <Border x:Name="border1" BorderBrush="Silver" BorderThickness="1" Height="100" HorizontalAlignment="Left" Margin="12,12,0,0" VerticalAlignment="Top" Width="376" Background="#FFB19C9C" AllowDrop="True" Drop="DropHere" UseLayoutRounding="True">
          <TextBlock TextWrapping="Wrap" Text="Drop Files Here." HorizontalAlignment="Center" VerticalAlignment="Center" />
        </Border>
    
    
        private void DropHere(object sender, DragEventArgs e)
        {
          InitializeComponent();
          IDataObject data = e.Data;
          if (data.GetDataPresent(DataFormats.FileDrop))
          {
            FileInfo[] files = data.GetData(DataFormats.FileDrop) as FileInfo[];
            foreach (var file in files)
            {
              switch (file.Extension)
              {
                case ".png":
                case ".jpg":
    
                  
                  FileStream fs = file.OpenRead();
                  BitmapImage bmp = new BitmapImage();
                  bmp.SetSource(fs);
                  image1.Source = bitmap; //イメージタグに画像を指定
                  break;
              }
            }
          }
        }
    
    2011年1月3日 14:06
  •  前に提示したサンプルは string で定義しているので実行時に指定された URI からイメージを取得しに行って作成するようになっています。この部分を「ImageSource」でバインドするようにしてみてください。

     ※バインドやビューモデル、ビューへの通知の仕組みなどの説明は端折ってますのでわからない場合は適時調べてください(^^;)

     私のサンプルと takahashi32 のコードを組み合わせた感じだと下のようなコードで実現できると思います。変更点はコメントで書いています。

    ◆XAML (MainPage.xaml)

    <Grid x:Name="LayoutRoot" Background="White">
     <Grid.RowDefinitions>
      <RowDefinition Height="120" />
      <RowDefinition Height="30" />
      <RowDefinition Height="*" />
     </Grid.RowDefinitions>
     <!-- ドロップエリア -->
     <Border x:Name="border1" BorderBrush="Silver" BorderThickness="1" Height="100" HorizontalAlignment="Left" Margin="12,12,0,0" VerticalAlignment="Top" Width="376" Background="#FFB19C9C" AllowDrop="True" Drop="DropHere" UseLayoutRounding="True">
      <TextBlock TextWrapping="Wrap" Text="Drop Files Here." HorizontalAlignment="Center" VerticalAlignment="Center" />
     </Border>
     <!-- 一応こんな感じに定義していたものと想定して Image を記述 -->
     <Image Grid.Row="1" x:Name="image1"></Image>
     <!-- ListBox -->
     <ListBox Grid.Row="2" ItemsSource="{Binding Items}">
      <ListBox.ItemTemplate>
       <DataTemplate>
        <!-- バインドするプロパティ名を Path から Image に変更 (名前は一致すればなんでもいいです) -->
        <Image Margin="5" Width="100" Height="100" Source="{Binding Image}" />
       </DataTemplate>
      </ListBox.ItemTemplate>
     </ListBox>
    </Grid>
    

    ◆コード (MainPage.xaml.cs)

    public partial class MainPage : UserControl
    {
     private ViewModel viewModel; // バインドしているインスタンスを使うので保持する形に
     public class Item
     {
      public ImageSource Image { get; set; } // string Path → ImageSource Image に変更
     }
     public class ViewModel
     {
      private ObservableCollection<Item> _items = new ObservableCollection<Item>();
      public ObservableCollection<Item> Items
      {
       get { return this._items; }
       set { this._items = value; }
      }
     }
     public MainPage()
     {
      InitializeComponent();
      this.viewModel = new ViewModel(); // フィールドに持つ
      this.DataContext = viewModel; // ビューにバインド
     }
     private void DropHere(object sender, DragEventArgs e)
     {
      IDataObject data = e.Data;
      if (data.GetDataPresent(DataFormats.FileDrop))
      {
       FileInfo[] files = data.GetData(DataFormats.FileDrop) as FileInfo[];
       foreach (var file in files)
       {
        switch (file.Extension)
        {
         case ".png":
         case ".jpg":
          FileStream fs = file.OpenRead();
          BitmapImage bmp = new BitmapImage();
          bmp.SetSource(fs);
          //image1.Source = bmp; //イメージタグに画像を指定
          // 作成したイメージをビューにバインドしているアイテム一覧に追加
          // ※ ObservableCollection 使ってるのでそのままビューに変更が通知されます
          this.viewModel.Items.Add(new Item() { Image = bmp, });
          break;
        }
       }
      }
     }
    }
    

    おのでら / ソーサリーフォース(http://sorceryforce.com/)
    • 回答としてマーク Shingo Tada 2011年1月4日 6:33
    2011年1月3日 15:16
  • ありがとうございます!

    教えていただいた通りやったところ、うまくいきました。大変お手数をおかけしました。

    これで先に進めます。

    2011年1月4日 6:33