2017-02-16 5 views
0

Canvasから拡張されたカスタムコントロールがあり、その子としてクラスShapeのインスタンスのみを受け入れることができます。以下のコードを検討してください。XAMLでプロパティセッターが動作しない

public class SvgGroup : Canvas 
{ 

    // ... 

    public Brush Fill 
    { 
     // Retuns the fill brush value of all the shape children, if they are all the same. Otherwise, the default value of Brush is returned 
     get 
     { 
      Brush rtn = default(Brush); 
      for (int i = 0; i < ShapeChildren.Count; i++) 
      { 
       Shape shape = ShapeChildren[i]; 
       if (i == 0) // First loop 
       { 
        rtn = shape.Fill; 
       } 
       else if (rtn != shape.Fill) // Children shapes have different Fill value 
       { 
        return default(Brush); 
       } 
      } 

      return rtn; 
     } 

     // Sets the fill brush value of all the shape children 
     set 
     { 
      foreach (Shape shape in ShapeChildren) 
      { 
       shape.Fill = value; 
      } 
     } 
    } 

    // ... 
} 

XAMLでFillプロパティを設定すると何も起こりません。ただし、コードビハインドの塗りつぶしの設定は動作します。

私は依存関係のプロパティを考えていましたが、このシナリオの実装は非常に難しいかもしれません。

+0

。 – Clemens

+0

true、これはXAMLが解析されたときに発生します。これは私がDependencyPropertyについて考えていた理由です –

+0

どうすればそれが役に立ちますか? Fillが設定された後も、追加された子要素に反応する必要があります。 – Clemens

答えて

1

私はあなたが2つの依存関係プロパティを定義する必要がありますし、あなたが更新され、それらのいずれかを維持すべきだと思う:あなたは新しい図形を追加したり、個別にそのブラシを変更したときにするときには、例えば(適切OnShapeBrushChanged()を呼び出す必要があります

public class SvgGroup : Canvas 
{ 

    public Brush Fill 
    { 
     get { return (Brush)GetValue(FillProperty); } 
     set { SetValue(FillProperty, value); } 
    } 
    public static readonly DependencyProperty FillProperty 
    = DependencyProperty.Register(
     "Fill", 
     typeof(Brush), 
     typeof(SvgGroup), 
     new FrameworkPropertyMetadata(Brushes.Red, OnFillPropertyChanged) 
    ); 

    private static void OnFillPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     SvgGroup svg = (SvgGroup)d; 
     if (e.NewValue != null && !e.NewValue.Equals(e.OldValue)) 
     { 
      foreach (Shape shape in d.ShapeChildren) 
      { 
       shape.Fill = (Brush)e.NewValue; 
      } 
      d.OnShapeBrushChanged(); // Note that you should call this method in some other places too. 
     } 
    } 

    public Brush FillDifferentBrush 
    { 
     get { return (Brush)GetValue(IsFillDifferentProperty); } 
    } 

    public static readonly DependencyProperty FillDifferentProperty 
     = DependencyProperty.Register(
       "FillDifferentBrush", 
       typeof(Brush), 
       typeof(SvgGroup), 
       new PropertyMetadata(null) 
     ); 




    void OnShapeBrushChanged() 
    { 
     Brush rtn = default(Brush); 
     for (int i = 0; i < ShapeChildren.Count; i++) 
     { 
      Shape shape = ShapeChildren[i]; 
      if (i == 0) // First loop 
      { 
       rtn = shape.Fill; 
      } 
      else if (rtn != shape.Fill) // Children shapes have different Fill value 
      { 
       SetValue(FillDifferentProperty, default(Brush)); 
      } 
      else 
       SetValue(FillDifferentProperty, rtn); 
     } 
    } 

} 

、または(ItemsControlのHasItemsプロパティのようなものです)。

+0

は、シェイプの子のブラシの変更を「聴く」方法がありますか? –

+0

わかりません。ただし、ユーザーが特定の図形のブラシを直接変更することはできません。このためにパブリックメソッドを作成します。それ以外の場合は、新しいItemを追加/削除したときとFillプロパティを設定したときの2つの場合にのみブラシをチェックする必要があります。 – Ron

+0

IsFillDifferentBrushの目的は何ですか?それは完全に冗長なようです。また、コードサンプルで実際に使用するのではなく、その使用法について説明しません。それに加えて、依存関係プロパティの命名規則に従わない。プロパティが 'IsFillDifferentBrush'である場合、DependencyPropertyフィールドの名前は' IsFillDifferentBrushProperty'で、registerに渡される名前は '' IsFillDifferentBrush''でなければなりません。 – Clemens

0

Attached PropertyProperty Value Inheritanceのふるまいで宣言できます。

プロパティがいずれかの親要素に設定されている場合、その値はすべての子要素に継承されます。要素がShapeであるかどうかをチェックし、最後に継承されたブラシをShapeのFillプロパティに適用するPropertyChangedコールバックがあります。

public static class ChildFillEx 
{ 
    public static readonly DependencyProperty ChildFillProperty = 
     DependencyProperty.RegisterAttached(
      "ChildFill", typeof(Brush), typeof(ChildFillEx), 
      new FrameworkPropertyMetadata(
       null, 
       FrameworkPropertyMetadataOptions.Inherits, 
       ChildFillPropertyChanged)); 

    public static Brush GetChildFill(DependencyObject obj) 
    { 
     return (Brush)obj.GetValue(ChildFillProperty); 
    } 

    public static void SetChildFill(DependencyObject obj, Brush value) 
    { 
     obj.SetValue(ChildFillProperty, value); 
    } 

    private static void ChildFillPropertyChanged(
     DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     var shape = obj as Shape; 
     if (shape != null) 
     { 
      shape.Fill = (Brush)e.NewValue; 
     } 
    } 
} 

あなたはこのようにそれを使用する:あなたは `SvgGroup.Fill`が設定された後に追加されたすべての子の` Fill`プロパティを設定しない

<Canvas local:ChildFillEx.ChildFill="Red"> 
    <Rectangle Width="100" Height="100" /> 
</Canvas> 
+0

こんにちは、関連する質問:[this](http://stackoverflow.com/a/8802620/5615980)に同意しますか?ありがとう – Ron

+0

全くありません。たとえば、関連付けられた動作について考えてみてください。ただし、値の継承を持つ依存関係プロパティは、通常、添付プロパティとして宣言する必要があります。 *カスタムプロパティを継承可能にするセクションを参照してください。https://msdn.microsoft.com/en-us/library/ms753197(v=vs.110).aspx – Clemens

+0

ありがとうございます。それは良い記事です。私はそれを読むでしょう。 – Ron

関連する問題