2010-04-06 17 views
7

Estoy creando un escritorio de juegos. Quería especificar el tamaño del campo (un campo es un cuadrado) como una propiedad adjunta y con este valor de conjunto de datos de ViewPort que dibujaría una matriz de 2x2 (y el modo de mosaico haría el resto de la mesa de juego).TemplateBinding con convertidor: ¿qué pasa?

No entiendo muy bien lo que está mal porque el enlace no funciona.

línea de prueba en XAML para el comportamiento me gustaría tener:

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

El mostrador de juego se basa en esta muestra de DrawingPaint: http://msdn.microsoft.com/en-us/library/aa970904.aspx (una imagen es aquí)

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> 

Converter y propiedad de definición:

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(); 
     } 
    } 
} 

Respuesta

11

TemplateBindings solo funcionan para las propiedades de dependencia definidas en el control que se está modelando (en un ControlTemplate). Sólo tiene que cambiar esto alrededor a ser un Binding con un RelativeSource de AncestorType (también, las propiedades asociadas requieren paréntesis para ser utilizado en un enlace):

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

Editar ha actualizado la RelativeSource unión, ya que no era definido dentro de ControlTemplate.

+0

He encontrado este error en la ventana de salida de Visual Studio: System.Windows.Data Error: 2: No se puede encontrar FrameworkElement o FrameworkContentElement que rige para el elemento de destino. BindingExpression: Path = (0); DataItem = null; el elemento objetivo es 'DrawingBrush' (HashCode = 35191196); target property es 'Viewport' (tipo 'Rect') –

+0

Disculpe, no miré detenidamente la propiedad que estaba configurando. He actualizado la respuesta para que realmente funcione. –

+0

Gracias, me enteré de su ejemplo anterior. –