2011-08-03 1 views
0

私はWPFが初めてです。WPFでマルチイメージの自動調整バックグラウンドを実装するにはどうすればよいですか?AndroidのNine Patchに似ていますか?

私は2つの「ペイン」、マスターペイン、詳細ペインに分割されたアプリを持っています。マスターペインは背が高く、幅が狭く、左揃えです。詳細ペインは幅が広く、アプリ領域の大部分を占め、右揃えになっています。

ここでの目標は、各ペインに対してサイズ変更可能なイメージの背景を実装することです。このコンセプトは、AndroidのNine Patch(see Nine Patch documentation)メカニズムに似ています。実際、このWPFアプリは、同じアプリのAndroid版で使用されているのとまったく同じソースPNGを使用します。ご覧のとおり、これはクロスプラットフォームのアプリです。両方のプラットフォーム間でビジネスオブジェクトとロジックを共有しますが、UI実装はアプリが異なるところです。

Nine Patchドキュメントを読むとき、を無視します。ドキュメントではボタンでこの概念のみを説明しています。どのような種類のビューでも実装できます。私はすでに、アプリの背景など、iOSで動作するコンセプトを持っています。今はWPFとSilverlightにこの概念を移植するだけです。

各ペインのルートコンテナは、System.Windows.Controlsです。 グリッド。私が知ることから、これを処理する最良の方法は、グリッドを3×3の構造に分割し、WPFプロパティバインディングを使用してそれぞれの適切なグリッドセクションにNine Patchイメージの各部分を適用することです。 ImageBrush。しかし、私はWPFでグリッドを構築すること、またはそのためのバインディング機能に完全に慣れていません。そして、ウィンドウのサイズ変更はどのように処理されますか?

これに関するアドバイスをいただければ幸いです。ありがとう。

編集:この場合、私はXAMLの利便性がないと言及する必要があります。これはすべてプログラマチックに行う必要があります。

EDIT: loxxyのアドバイスの成果を披露し、次のステップの詳細についてお尋ねします。ここに私の実装の結果は(私は以下の多くの質問を持っている、ように読んでください)今のところです:

Nine Patch for WPF

NinePatchImage npi = new NinePatchImage([some params]); 
Grid backgroundGrid = new Grid(); 
backgroundGrid.ColumnDefinitions.Clear(); 
backgroundGrid.RowDefinitions.Clear(); 
backgroundGrid.ColumnDefinitions.Add(
    // first column 
    new ColumnDefinition() 
    { 
     Width = new GridLength(1, GridUnitType.Auto), 
    }); 
backgroundGrid.ColumnDefinitions.Add(
    // second column 
    new ColumnDefinition() 
    { 
     Width = new GridLength(1, GridUnitType.Star) 
    }); 
backgroundGrid.ColumnDefinitions.Add(
    // third column 
    new ColumnDefinition() 
    { 
     Width = new GridLength(1, GridUnitType.Auto) 
    }); 
backgroundGrid.RowDefinitions.Add(
    // first row 
    new RowDefinition() 
    { 
     Height = new GridLength(1, GridUnitType.Auto), 
    }); 
backgroundGrid.RowDefinitions.Add(
    // second row 
    new RowDefinition() 
    { 
     Height = new GridLength(1, GridUnitType.Star) 
    }); 
backgroundGrid.RowDefinitions.Add(
    // third row 
    new RowDefinition() 
    { 
     Height = new GridLength(1, GridUnitType.Auto) 
    }); 

var imageTopLeft = new Image() { Source = (npi.TopLeft != null) ? npi.TopLeft : null, Stretch = Stretch.None }; 
var imageTopCenter = new Image() { Source = (npi.TopCenter != null) ? npi.TopCenter : null, Stretch = Stretch.None }; 
var imageTopRight = new Image() { Source = (npi.TopRight != null) ? npi.TopRight : null, Stretch = Stretch.None }; 
var imageMiddleLeft = new Image() { Source = (npi.MiddleLeft != null) ? npi.MiddleLeft : null, Stretch = Stretch.None }; 
var imageMiddleCenter = new Image() { Source = (npi.MiddleCenter != null) ? npi.MiddleCenter : null, Stretch = Stretch.None }; 
var imageMiddleRight = new Image() { Source = (npi.MiddleRight != null) ? npi.MiddleRight : null, Stretch = Stretch.None }; 
var imageBottomLeft = new Image() { Source = (npi.BottomLeft != null) ? npi.BottomLeft : null, Stretch = Stretch.None }; 
var imageBottomCenter = new Image() { Source = (npi.BottomCenter != null) ? npi.BottomCenter : null, Stretch = Stretch.None }; 
var imageBottomRight = new Image() { Source = (npi.BottomRight != null) ? npi.BottomRight : null, Stretch = Stretch.None }; 

backgroundGrid.Children.Add(imageTopLeft); Grid.SetColumn(imageTopLeft, 0); Grid.SetRow(imageTopLeft, 0); 
backgroundGrid.Children.Add(imageTopCenter); Grid.SetColumn(imageTopCenter, 1); Grid.SetRow(imageTopCenter, 0); 
backgroundGrid.Children.Add(imageTopRight); Grid.SetColumn(imageTopRight, 2); Grid.SetRow(imageTopRight, 0); 
backgroundGrid.Children.Add(imageMiddleLeft); Grid.SetColumn(imageMiddleLeft, 0); Grid.SetRow(imageMiddleLeft, 1); 
backgroundGrid.Children.Add(imageMiddleCenter); Grid.SetColumn(imageMiddleCenter, 1); Grid.SetRow(imageMiddleCenter, 1); 
backgroundGrid.Children.Add(imageMiddleRight); Grid.SetColumn(imageMiddleRight, 2); Grid.SetRow(imageMiddleRight, 1); 
backgroundGrid.Children.Add(imageBottomLeft); Grid.SetColumn(imageBottomLeft, 0); Grid.SetRow(imageBottomLeft, 2); 
backgroundGrid.Children.Add(imageBottomCenter); Grid.SetColumn(imageBottomCenter, 1); Grid.SetRow(imageBottomCenter, 2); 
backgroundGrid.Children.Add(imageBottomRight); Grid.SetColumn(imageBottomRight, 2); Grid.SetRow(imageBottomRight, 2); 

Grid contentArea = new Grid() { ColumnDefinitions = { new ColumnDefinition() } }; 
// setup contentArea here blah blah blah 

// a containing grid 
Grid container = new Grid(); 
// add the background grid to the containing grid 
container.Children.Add(backgroundGrid); 
// add the content grid to the background grid's UIElement collection 
backgroundGrid.Children.Add(contentArea); 
// set the backgroundGrid's column position 
Grid.SetColumn(backgroundGrid, 0); 
// set the backgroundGrid's row position 
Grid.SetRow(backgroundGrid, 0); 
// set the content area's column position 
Grid.SetColumn(contentArea, 1); 
// set the content area's row position 
Grid.SetRow(contentArea, 1); 

NOW、私は正しい方向に伸ばすか、タイル、トップとサイドの画像を取得する必要があります、xまたはy。 Image WPF要素にはいくつかのオプションがありますが、ストレッチはx方向とy方向の両方で発生しますが、これらの2つの次元のうちの1つだけにストレッチが必要です。また、必要に応じて(上の画像の場合のように)、私はxまたはyのいずれかでTILEすることができる必要があります。 image要素はこれをサポートしていませんが、ImageBrushクラスはこれらの種類のものに非常に役立つことがあります。 ImageBrushをImage要素、またはそのような他のタイプの要素に直接バインドできますか?

+0

としてバインディングでコンバータを実装ところで、そのデータの全ては、ダミーデータである:) – NovaJoe

+0

はちょうど私がこのすべて整理しまったことを言及したかったです。よく働く!!! – NovaJoe

答えて

2

2つの枠(リンク内のような)が必要な場合、なぜ3x3グリッドが必要だと思いますか?単に背景に関するものなら、ImageBrushは、かなり違って2枚のパネルをペイントするのに十分です。

また、パネルを右揃え、左揃えなどで話すときは、DockPanelを使用することをお勧めします。ドックパネルの最後の子は、親コンテナを埋めるように引き伸ばされます。

私はあなたがバインディングでやろうとしている部分を得ていませんでした。あなたは、パネル内のコンテンツをバインドすることについて話していますか、またはいくつかのソースで背景イメージをバインドしようとしていますか?


私はnineパッチのドキュメントを読みましたが、9つの異なるイメージに関連する9つのパッチは見つかりませんでした。 ninepatchは、単に境界線を持つ伸縮可能な画像であると感じました。

とにかく、9つの画像が背景として必要な場合は、子グリッド内の画像を使用できます。複数のコンテンツをグリッド(同じ行と列)に配置すると、最後の子がグリッドの最上位レイヤを占有します。

<Grid> 
      <Grid> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="*" /> 
        <RowDefinition Height="*"/> 
        <RowDefinition Height="*"/> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="*"/> 
        <ColumnDefinition Width="*"/> 
        <ColumnDefinition Width="*"/> 
       </Grid.ColumnDefinitions> 

       <Image Source="Img1.png" Grid.Row="0" Grid.Column="0"/> 
       <Image Source="Img2.png" Grid.Row="0" Grid.Column="1"/> 
       <Image Source="Img3.png" Grid.Row="0" Grid.Column="2"/> 
       <Image Source="Img4.png" Grid.Row="1" Grid.Column="0"/> 
       <Image Source="Img5.png" Grid.Row="1" Grid.Column="1"/> 
       <Image Source="Img6.png" Grid.Row="1" Grid.Column="2"/> 
       <Image Source="Img7.png" Grid.Row="2" Grid.Column="0"/> 
       <Image Source="Img8.png" Grid.Row="2" Grid.Column="1"/> 
       <Image Source="Img9.png" Grid.Row="2" Grid.Column="2"/> 
      </Grid> 

      <Grid> 
       <Label>This Content is put in front.</Label> 
      </Grid> 
</Grid> 

ここでバインディング部分。画像ソースを動的に更新していますか?私は9つの画像の画像ソースを変更するのですか?その後、バインディングのみが必要です。それが単にソースであれば、なぜURIを直接指定しないのでしょうか。

しかし、あなたが本当に必要な場合は結合、ImagePathのは、文字列をある

<Image Source="{Binding ImagePath}" /> 

。これはイメージソースを文字列として指定できる組み込みコンバータを使用しています。

しかし、(銀色のバインディングで)問題を避けるために、独自のコンバータを使用することができます。

public sealed class ImageConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, 
          object parameter, CultureInfo culture) 
    { 
     try 
     { 
      return new BitmapImage(new Uri((string)value)); 
     } 
     catch 
     { 
      return new BitmapImage(); 
     } 
    } 

    public object ConvertBack(object value, Type targetType, 
           object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

<Image Source="{Binding Path=ImagePath, Converter=...}" /> 
+0

各ペインは3x3であり、レイアウト全体では3x3ではありません。これを単純化しましょう。 2つのペインのコンセプトを無視してください。 1つのペインに対処しましょう。私はRadDockPanelをメインコンテナとして使用しています。そして、はい、Nine Patchイメージの9個のそれぞれに1つのソースイメージにバックグラウンドイメージをバインドしようとしています。 Nine Patchのドキュメントを読んだことがありますか? – NovaJoe

+0

編集内容をご覧ください。 – loxxy

+0

優秀!!!ありがとう!私はXAMLを使用していませんが、このすべてをC#で構築するにはAPIを使用するだけで十分です。私が今までに受けた最高の答えの一つ。あなたの9つのパッチ/イメージソースに関する質問:私はNinePatchクラスを持っていて、そのコンストラクタにPNGをとります。画像はスライスされ、建設時にダイスされ、9つの部分がプライベートバーに保持されます。このクラスには、9つの各パートのインスタンスゲッターメソッドもあります。したがって、私はNinePatchインスタンスにバインドし、値コンバータを使用し、必要に応じて適切な部分を取得します。これにより、プラットフォーム間で同じファイルを使用することができます。 – NovaJoe

関連する問題