2010-04-06 46 views
7

我正在创建一个游戏桌。我想指定字段大小(一个字段是一个正方形)作为附加属性,并使用ViewPort的这个数据集值来绘制2x2矩阵(并且平铺模式将完成游戏桌面的其余部分)。TemplateBinding与转换器 - 有什么不对?

我很不知所措,因为绑定不起作用。

检测线在XAML的行为,我想有:

<DrawingBrush Viewport="0,0,100,100" ViewportUnits="Absolute" TileMode="None"> 

游戏桌是基于这个样本DrawingPaint的:http://msdn.microsoft.com/en-us/library/aa970904.aspx(图像是这里)

XAML:

<Window x:Class="Sokoban.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:Sokoban" 
    Title="Window1" Height="559" Width="419"> 
    <Window.Resources> 
     <local:FieldSizeToRectConverter x:Key="fieldSizeConverter" /> 
     <Style x:Key="GameDesk" TargetType="{x:Type Rectangle}"> 
      <Setter Property="local:GameDeskProperties.FieldSize" Value="50" /> 
      <Setter Property="Fill"> 
       <Setter.Value> 
        <!--<DrawingBrush Viewport="0,0,100,100" ViewportUnits="Absolute" TileMode="None">--> 
        <DrawingBrush Viewport="{TemplateBinding local:GameDeskProperties.FieldSize, Converter={StaticResource fieldSizeConverter}}" ViewportUnits="Absolute" TileMode="None"> 
         <DrawingBrush.Drawing> 
          <DrawingGroup> 
           <GeometryDrawing Brush="CornflowerBlue"> 
            <GeometryDrawing.Geometry> 
             <RectangleGeometry Rect="0,0,100,100" /> 
            </GeometryDrawing.Geometry> 
           </GeometryDrawing> 

           <GeometryDrawing Brush="Azure"> 
            <GeometryDrawing.Geometry> 
             <GeometryGroup> 
              <RectangleGeometry Rect="0,0,50,50" /> 
              <RectangleGeometry Rect="50,50,50,50" /> 
             </GeometryGroup> 
            </GeometryDrawing.Geometry> 
           </GeometryDrawing> 
          </DrawingGroup> 
         </DrawingBrush.Drawing> 
        </DrawingBrush> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </Window.Resources> 

    <StackPanel> 
     <Rectangle Style="{StaticResource GameDesk}" Width="300" Height="150" />   
    </StackPanel> 
</Window> 

转换器和属性定义:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Windows.Controls; 
using System.Windows; 
using System.Diagnostics; 
using System.Windows.Data; 

namespace Sokoban 
{ 
    public class GameDeskProperties : Panel 
    { 

     public static readonly DependencyProperty FieldSizeProperty; 

     static GameDeskProperties() 
     { 
      PropertyChangedCallback fieldSizeChanged = 
       new PropertyChangedCallback(OnFieldSizeChanged); 
      PropertyMetadata fieldSizeMetadata = 
       new PropertyMetadata(50, fieldSizeChanged); 

      FieldSizeProperty = DependencyProperty.RegisterAttached("FieldSize", 
       typeof(int), typeof(GameDeskProperties), fieldSizeMetadata); 
     } 

     public static int GetFieldSize(DependencyObject target) 
     { 
      return (int)target.GetValue(FieldSizeProperty); 
     } 

     public static void SetFieldSize(DependencyObject target, int value) 
     { 
      target.SetValue(FieldSizeProperty, value); 
     } 


     static void OnFieldSizeChanged(DependencyObject target, 
           DependencyPropertyChangedEventArgs e) 
     { 
      Debug.WriteLine("FieldSize just changed: " + e.NewValue); 
     } 
    } 

    [ValueConversion(/* sourceType */ typeof(int), /* targetType */ typeof(Rect))] 
    public class FieldSizeToRectConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      Debug.Assert(targetType == typeof(int)); 

      int fieldSize = int.Parse(value.ToString()); 
      return new Rect(0, 0, 2 * fieldSize, 2 * fieldSize); 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      // should not be called in our example 
      throw new NotImplementedException(); 
     } 
    } 
} 

回答

11

TemplateBindings只适用于在模板化控件上定义的依赖项属性(在ControlTemplate中)。你只需要关掉这个到处是BindingAncestorTypeRelativeSource(也,附加属性需要括号中结合使用):

... 
<DrawingBrush Viewport="{Binding Path=(local:GameDeskProperties.FieldSize), Converter={StaticResource fieldSizeConverter}, RelativeSource={RelativeSource AncestorType={x:Type Rectangle}}}" 
... 

编辑更新了RelativeSource约束力的,因为它是不定义在ControlTemplate的内部。

+0

我在Visual Studio的输出窗口中发现了这个错误: System.Windows.Data错误:2:找不到目标元素的管理FrameworkElement或FrameworkContentElement。 BindingExpression:路径=(0);的DataItem = NULL;目标元素是'DrawingBrush'(HashCode = 35191196);目标属性是'视口'(类型'Rect') – 2010-04-06 16:18:52

+0

对不起,我没有仔细看看你设置的财产。我已经更新了答案,以便它真正起作用。 – 2010-04-06 22:30:50

+0

谢谢,我从你以前的例子中发现了。 – 2010-04-08 18:48:04