2010-04-06 10 views
7

Sto creando una console di gioco. Volevo specificare la dimensione del campo (un campo è un quadrato) come proprietà associata e con questo valore di set di dati di ViewPort che disegnerebbe matrice 2x2 (e la modalità tile avrebbe fatto il resto del game desk).TemplateBinding with Converter - cosa c'è che non va?

Sono abbastanza in perdita ciò che è sbagliato perché l'associazione non funziona.

linea di test in XAML per il comportamento mi piacerebbe avere:

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

La scrivania gioco è basato su questo campione di DrawingPaint: http://msdn.microsoft.com/en-us/library/aa970904.aspx (un'immagine è qui)

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 e proprietà definizione:

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

risposta

11

TemplateBindings funziona solo per le proprietà di dipendenza definite sul controllo in corso di creazione (in un ControlTemplate). Hai solo bisogno di cambiare questo intorno ad essere un Binding con un RelativeSource di AncestorType (anche, proprietà associate richiedono parentesi per essere utilizzato in un vincolante):

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

Modifica Aggiornato il RelativeSource vincolante, in quanto non era definito all'interno di un ControlTemplate.

+0

Ho trovato questo errore nella finestra di output di Visual Studio: System.Windows.Data Errore: 2: Impossibile trovare il framework FrameworkElement o FrameworkContentElement per l'elemento di destinazione. BindingExpression: Path = (0); DataItem = null; l'elemento target è 'DrawingBrush' (HashCode = 35191196); la proprietà target è 'Viewport' (digita 'Rect') –

+0

Scusa, non ho guardato attentamente la proprietà che stavi impostando. Ho aggiornato la risposta in modo che funzioni effettivamente. –

+0

Grazie, ho scoperto dal tuo esempio precedente. –

Problemi correlati