代码之家  ›  专栏  ›  技术社区  ›  MartyIX

带转换器的模板绑定-怎么了?

  •  7
  • MartyIX  · 技术社区  · 15 年前

    我正在创建一个游戏桌。我想指定字段大小(一个字段是一个正方形)作为附加属性,并使用这个将绘制2x2矩阵的视区数据集值(平铺模式将完成游戏桌的其余部分)。

    我完全不知怎么回事,因为装订不好。

    在XAML中测试我希望拥有的行为:

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

    游戏桌基于以下绘画示例: 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();
            }
        }
    }
    
    1 回复  |  直到 15 年前
        1
  •  11
  •   Abe Heidebrecht    15 年前

    TemplateBindings 仅适用于在要模板化的控件上定义的依赖项属性(在 ControlTemplate )你只要把这个换成 Binding 用一个 RelativeSource 属于 AncestorType (此外,附加属性要求在绑定中使用括号):

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

    编辑 更新了 相对资源 绑定,因为它在 控件模板 .