2009-07-26 12 views
1

派生した要素<UserControl>の要素を基底の要素にバインドする方法<UserControl>XAML - 派生した<UserControl>の要素をベースの要素にバインドする方法<UserControl>?

TileというUserControlをベースクラスとして定義しました。これは、抽象基本クラス、もし私がそれから派生したオブジェクトをインスタンス化しようとしたときにXAMLがボークしないならば...

とにかく、これまでのところ、Tileは単一の依存性プロパティ:OuterShapeしか含んでいません。これはSystem.Windows.Shapes.Shapeオブジェクト(抽象クラ​​ス)です。したがって、すべてのタイルは、レンダリングのために、それらに関連付けられた何らかの種類の視覚的形状を有することになる。しかし、タイルにはさまざまな種類があります。いくつかはSystem.Windows.Shapes.Paths、System.Windows.Shapes.Polygonsなどがあります。

これで、最初に派生したUserControl:PolyTileを作成しています。名前が示すように、これはSystem.Windows.Shapes.Polygonを "OuterShape"プロパティとして使用するTileです。

私が遭遇している問題は、XAML <Polygon>要素を基本クラスのShapeプロパティに正しくバインドする方法がわかりません。

/************ 
** Tile.cs ** 
************/ 
// This class contains a generic shape, and that's all. 
// This class does NOT have a XAML file to go with it. It is purely code implemented. 
public class Tile : System.Windows.Controls.UserControl 
{ 
    public static readonly System.Windows.DependencyProperty OuterShapeProperty 
     = System.Windows.DependencyProperty.Register( "OuterShape", 
                 typeof(System.Windows.Shapes.Shape), 
                 typeof(Tile)); 
    public System.Windows.Shapes.Shape OuterShape 
    { get { return (System.Windows.Shapes.Shape)GetValue(OuterShapeProperty); } 
     set { SetValue(OuterShapeProperty, (System.Windows.Shapes.Shape)value); } 
    } 
} 

........................

<!--***************** 
*** PolyTile.xaml *** 
******************--> 
<local:Tile x:Name="__PolyTile__" x:Class="WPFApplication1.PolyTile" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WPFApplication1"> 
    <Grid Name="grdMain"> 
     <Polygon Name="OuterPoly" /> 
      <!--OuterPoly needs to be data-bound (OneWay) 
      to the OuterShape property of the Tile UserControl. 
      That way, when my derived class sets OuterShape to a new <Polygon> element, 
      OuterShape will show up on the screen as a <Polygon>--> 
    </Grid> 
</local:Tile> 

.........

/**************** 
** PolyTile.cs ** 
****************/ 
// This class encapsulates a tile that is in the shape of a specified <Polygon> element. 
/// <summary> 
/// Interaction logic for PolyTile.xaml 
/// </summary> 
public partial class PolyTile : Tile // Derived from Tile 
{ 
    public PolyTile() 
    { 
     InitializeComponent(); 

     System.Windows.Data.BindingExpressionBase BindExp; 
     PolyConverter polyConverter = new PolyConverter(); 

     System.Windows.Data.Binding PolyBinding = new System.Windows.Data.Binding("OuterPoly"); 
     PolyBinding.Source = __PolyTile__; 
     PolyBinding.Mode = System.Windows.Data.BindingMode.OneWayToSource; 
     PolyBinding.Converter = polyConverter; 
     BindExp = __PolyTile__.SetBinding(Tile.OuterShapeProperty, PolyBinding); 
    } 



    // The framework won't convert a base object into a derived object without an explicit cast ... 
    // ... in this case, that means I have to make a custom DataConverter. 
    [System.Windows.Data.ValueConversion(typeof(System.Windows.Shapes.Polygon), typeof(System.Windows.Shapes.Shape))] 
    protected class PolyConverter : System.Windows.Data.IValueConverter 
    { 
     public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { return value; } 
     // OneWayToSource binding: Thus the Convert method is never used. 
     // Rather, ConverBack is used to cast the base <Shape> into a derived <Polygon> 

     public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (value.GetType() == typeof(System.Windows.Shapes.Polygon)) 
       return value; 
      else 
       return System.Windows.DependencyProperty.UnsetValue; 
     } 
    } 
} 

........私は、XAMLでこのバインディングを設定するためのあらゆる可能な方法が表示されません。 (私はすべてを考えたと言ってもいいほどデータコンテキストを理解していませんが...)

したがって、私は手作業でバックコードを設定しようとしました。私は、バインディングパスとソースとターゲットの要素を整理するさまざまな方法を試しました。私は致命的な例外やPathErrorやUpdateSourceErrorのようなものが似ているたびに取得します。

誰かが私が間違っていることを知っていますか?
アドバイスをいただければ幸いです!

<TextBlock 
    Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ParentUserControl}}, Path=MyProperty}" /> 

またはあなたは私が読みやすいと思います要素名のバインディングを、使用することができます - :

答えて

0

それは行うことができますをテストするために書いた小さなテストプロジェクトです。

デフォルトのデータコンテキストが完全に動作することに注意することが重要であるXAMLのオブジェクト構文を使用して、あなたは非常に明示的に取得しようとすると、問題が発生しますたとえばをあなたにElementName="__PolyTile__"を追加する場合に失敗しますバインディング結合。

このソリューションでは、データコンバータは不要です。おそらく少しのタイプセーフティーを犠牲にしても、これによりコードははるかに簡単になります。

<!--***************** 
*** PolyTile.xaml *** 
******************--> 
<local:Tile x:Name="__PolyTile__" x:Class="WPFApplication1.PolyTile" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WPFApplication1"> 

    <local:Tile.OuterShape> 
     <Binding Path="OuterPoly" Mode="OneWayToSource" /> 
    </local:Tile.OuterShape> 

    <Grid Name="grdMain"> 
     <Polygon Name="OuterPoly" /> 
    </Grid> 

</local:Tile> 
2

あなたはこのあなたが相対的なソースを使用することができる方法

のカップル行うことができます。 (あなたがXを使用する必要があります。XAMLファイルで全体のコントロールに名前を付けるために、ユーザーコントロール上の名前の構文を

<TextBlock 
    Text="{Binding ElementName=childUserControl, Path=MyProperty}" /> 

hereは、私はこの

+0

これはほとんど私の質問に答える。このコードを少し書き直して、子のTextBoxコントロールを親のTextBoxプロパティにバインドすることができますか?私はコントロール自体をバインドしようとしています - コントロールのプロパティではなく、 "Text" – Giffyguy

関連する問題