我正在创建游戏桌。我想指定字段大小(一个字段是一个正方形)作为附加属性,并使用ViewPort的此数据集值绘制2x2矩阵(而平铺模式将处理其余的游戏桌)。
我很茫然,因为绑定不起作用,这是怎么回事。
在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();
}
}
}
最佳答案
TemplateBindings
仅适用于在模板化控件(在ControlTemplate
中)上定义的依赖项属性。您只需要将其切换为Binding
且RelativeSource
的AncestorType
(同样,附加属性需要在绑定中使用括号):
...
<DrawingBrush Viewport="{Binding Path=(local:GameDeskProperties.FieldSize), Converter={StaticResource fieldSizeConverter}, RelativeSource={RelativeSource AncestorType={x:Type Rectangle}}}"
...
编辑更新了
RelativeSource
绑定,因为未在ControlTemplate
内部定义。