2017-10-17 92 views
-1

使用顯示可用平鋪背景列表的ComboBox工作。這只是一個簡單的ComboBox,其中一個ItemSource被設置爲MapTileBackground對象的集合。數據模板中的WPF綁定不能用於定製類

的MapTileBackground類與屬性完全定義:

public partial class MapTileBackground 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public byte[] Content { get; set; } 
    public Nullable<int> Color { get; set; } 
    public int StrokeColor { get; set; } 
    public byte StrokeThickness { get; set; } 
} 

其在一個單獨的庫中定義和我寧願不改變它。

我已經定義了一個簡單的形狀的擴展繪製背景::

public class MapTileBackgroundPreview : Shape 
{ 
    public static readonly DependencyProperty SizeProperty = DependencyProperty.Register("Size", typeof(Point), typeof(MapTileBackgroundPreview)); 
    public static readonly DependencyProperty TileBackgroundProperty = DependencyProperty.Register("TileBackground", typeof(MapTileBackground), typeof(MapTileBackgroundPreview)); 
    public MapTileBackgroundPreview() 
    { 
     layout = new Hex.Layout(Hex.Orientation.Flat, new Hex.Point(8, 8), new Hex.Point(4, 4)); 
     Size = new Point(8, 8); 
     TileBackground = null; 
    } 

    private Hex.Layout layout; 
    protected override Geometry DefiningGeometry 
    { 
     get 
     { 
      var points = layout.HexCorners(0, 0).ToArray(); 
      var path = new PathFigure(); 
      path.StartPoint = points[5].ToWin(); 
      for (var i = 0; i < 6; i++) 
       path.Segments.Add(new LineSegment(points[i].ToWin(), true)); 

      var geo = new PathGeometry(); 
      geo.Figures.Add(path); 
      return geo; 
     } 
    } 
    public Point Size 
    { 
     get 
     { 
      return (Point)GetValue(SizeProperty); 
     } 
     set 
     { 
      SetValue(SizeProperty, value); 
      layout.Size = value.ToHex(); 
      layout.Origin = new Hex.Point(layout.Size.X/2, layout.Size.Y/2); 
     } 
    } 

    public MapTileBackground TileBackground 
    { 
     get 
     { 
      return (MapTileBackground)GetValue(TileBackgroundProperty); 
     } 
     set 
     { 
      SetValue(TileBackgroundProperty, value); 

      if (value == null) 
      { 
       Fill = Brushes.Transparent; 
       Stroke = Brushes.Black; 
       StrokeThickness = 1; 
      } 
      else 
      { 
       Stroke = value.Stroke(); 
       StrokeThickness = value.StrokeThickness(); 
       Fill = value.Fill(layout.Orientation); 
      } 
     } 
    } 
} 

佈局只是屏幕像素座標和六方晶系之間的轉換工具。定義幾何只需添加6行的六角線。 TileBackground設置器在給定非空MapTileBackground時,會根據背景定義更新描邊和填充。我已經成功測試了這個控件(在組合框數據模板之外)。

和說:

<DataTemplate x:Key="TileListItemRenderer"> 
    <Grid Width="225"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="24"/> 
      <ColumnDefinition Width="75"/> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 
     <local:MapTileBackgroundPreview Grid.Row="0" Grid.Column="0" Size="12,12" VerticalAlignment="Center" HorizontalAlignment="Center" TileBackground="{Binding /}"/> 
     <Label Grid.Row="0" Grid.Column="1" Content="{Binding Name}" HorizontalAlignment="Left" VerticalAlignment="Center" FontWeight="Bold"/> 
     <TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding Description}" HorizontalAlignment="Stretch" VerticalAlignment="Top" TextWrapping="Wrap" /> 
    </Grid> 
</DataTemplate> 

所以我只是創建一個形狀,和兩個標籤,形狀綁定到當前MapTileBackground對象(組合框的ItemSource是MapTileBackground對象的集合),以及標籤名稱和說明。

我的問題是形狀始終繪製爲空(因爲在TileBackground爲null),並且從不調用setter。名稱標籤和描述文本塊的行爲與預期相同(顯示正確的文本)。在我的調試嘗試期間,我在預覽對象上創建了一個id屬性,然後調用TileBackground Setter並將其綁定到Id屬性(避免當前的對象綁定),同樣,TileBackgroundId setter從不被調用。我甚至添加了一個綁定到Id的新標籤,看看它是否正常工作,並按預期顯示了該標識。這些變化再次無效。打開下拉菜單時從不設置TileBackgroundId或TileBackground屬性。

<DataTemplate x:Key="TileListItemRenderer"> 
     <Grid Width="225"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto"/> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="24"/> 
       <ColumnDefinition Width="75"/> 
       <ColumnDefinition /> 
      </Grid.ColumnDefinitions> 
      <local:MapTileBackgroundPreview Grid.Row="0" Grid.Column="0" Size="12,12" VerticalAlignment="Center" HorizontalAlignment="Center" TileBackgroundId="{Binding Id}"/> 
      <Label Grid.Row="0" Grid.Column="0" Content="{Binding Id}" HorizontalAlignment="Left" VerticalAlignment="Center" FontWeight="Bold"/> 
      <Label Grid.Row="0" Grid.Column="1" Content="{Binding Name}" HorizontalAlignment="Left" VerticalAlignment="Center" FontWeight="Bold"/> 
      <TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding Description}" HorizontalAlignment="Stretch" VerticalAlignment="Top" TextWrapping="Wrap" /> 
     </Grid> 
    </DataTemplate> 

    public static readonly DependencyProperty TileBackgroundIdProperty = DependencyProperty.Register("TileBackgroundId", typeof(int), typeof(MapTileBackgroundPreview)); 

    public int TileBackgroundId 
    { 
     get 
     { 
      return (int)GetValue(TileBackgroundIdProperty); 
     } 
     set 
     { 
      SetValue(TileBackgroundIdProperty, value); 
      TileBackground = TMapTileBackgroundTool.Get(value); 
     } 
    } 

TMapTileBackgroundTool.Get()返回基於標識正確的對象。

我還測試了數據模板外部的MapTileBackgroundPreview設置TileBackgroundId的實例。

有什麼想法是怎麼回事?

+0

可以共享'Hex'?或者在上面的代碼中刪除它? – Iron

+0

在這種情況下,Hex是一個名稱空間別名。 – David

回答

1

的CLR包裝的依賴setter方法是不應該被設定爲WPF綁定引擎調用GetValueSetValue方法直接:

Setters not run on Dependency Properties?

Why are .NET property wrappers bypassed at runtime when setting dependency properties in XAML?

的getter和CLR wrapper屬性的setter應該分別爲分別調用GetValueSetValue方法。

如果您想在依賴屬性設置做一些事情,你應該註冊一個回調:

public static readonly DependencyProperty TileBackgroundIdProperty = DependencyProperty.Register("TileBackgroundId", typeof(int), typeof(MapTileBackgroundPreview), 
    new PropertyMetadata(0, new PropertyChangedCallback(TileBackgroundIdChanged))); 

public int TileBackgroundId 
{ 
    get 
    { 
     return (int)GetValue(TileBackgroundIdProperty); 
    } 
    set 
    { 
     SetValue(TileBackgroundIdProperty, value); 
    } 
} 

private static void TileBackgroundIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    MapTileBackgroundPreview ctrl = (MapTileBackgroundPreview)d; 
    ctrl.TileBackground = TMapTileBackgroundTool.Get((int)e.NewValue); 
} 
+0

我不能相信我在搜索答案或研究數據綁定時沒有遇到過,因此完全是我的錯。感謝快速回答。無論如何,我使用更改事件重新實現了所有三個屬性,並將Id綁定到TileBackgroundId時一切正常。當綁定\到TileBackground時,我仍然沒有收到任何東西。我可以用基於int的屬性居住,我只是想知道爲什麼它不能以第二種方式工作。謝謝。 – David