2010-04-06 35 views
7

Tôi đang tạo một bàn trò chơi. Tôi muốn xác định kích thước trường (một trường là một hình vuông) như một thuộc tính đính kèm và với giá trị thiết lập dữ liệu này của ViewPort sẽ vẽ ma trận 2x2 (và chế độ lát gạch sẽ làm phần còn lại của bàn trò chơi).TemplateBinding with Converter - có gì sai?

Tôi hoàn toàn mất mát điều gì là sai vì ràng buộc không hoạt động.

kiểm tra dòng trong XAML cho hành vi tôi muốn có:

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

Bàn Trò chơi được dựa trên mẫu này DrawingPaint: http://msdn.microsoft.com/en-us/library/aa970904.aspx (một hình ảnh là ở đây)

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> 

Chuyển đổi và định nghĩa thuộc tính:

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

Trả lời

11

TemplateBindings chỉ hoạt động đối với các thuộc tính phụ thuộc được xác định trên điều khiển được tạo khuôn mẫu (trong ControlTemplate). Bạn chỉ cần chuyển xung quanh đây là một Binding với một RelativeSource của AncestorType (cũng có, tài sản gắn liền yêu cầu ngoặc được sử dụng trong một ràng buộc):

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

Sửa Cập nhật các RelativeSource ràng buộc, vì nó không phải là được xác định bên trong của ControlTemplate.

+0

Tôi đã tìm thấy lỗi này trong cửa sổ đầu ra của Visual Studio: Lỗi System.Windows.Data: 2: Không thể tìm thấy khung điều chỉnh FrameworkElement hoặc FrameworkContentElement cho phần tử đích. BindingExpression: Đường dẫn = (0); DataItem = null; phần tử đích là 'DrawingBrush' (HashCode = 35191196); tài sản mục tiêu là 'Viewport' (loại 'Rect') –

+0

Xin lỗi, tôi đã không nhìn kỹ vào tài sản bạn đang thiết lập. Tôi đã cập nhật câu trả lời để nó thực sự hoạt động. –

+0

Cảm ơn, tôi đã phát hiện ra từ ví dụ trước của bạn. –