如何将派生<UserControl>
的元素绑定到基础<UserControl>
的元素?
我已经将名为Tile的UserControl定义为我的基类。这将是一个抽象的基类,如果XAML在我试图实例化从它派生的对象时不会犹豫不决......
无论如何,到目前为止,Tile只包含一个依赖属性:OuterShape。它是一个System.Windows.Shapes.Shape对象(也是抽象的)。因此:所有的瓷砖都会有一些与它们相关的视觉形状,用于渲染。但是有许多不同类型的Tiles--一些使用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中设置此绑定。 (虽然我不太清楚DataContexts,但我已经想到了所有的东西......)
因此,我尝试在后面的代码中手动设置绑定。我已经尝试了许多不同的方法来组织绑定路径以及源和目标元素。每次我得到致命异常或PathError或UpdateSourceError类似的东西。
有谁知道我做错了什么? 非常感谢任何建议!
答案 0 :(得分:2)
你可以通过几种方式做到这一点
你可以使用相对来源: -
<TextBlock
Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ParentUserControl}}, Path=MyProperty}" />
或者您可以使用元素名称绑定,我认为这更容易阅读。 (您必须在用户控件上使用x:Name语法来命名xaml文件中的整个控件。
<TextBlock
Text="{Binding ElementName=childUserControl, Path=MyProperty}" />
here是我写的一个测试项目
答案 1 :(得分: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>