Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/89.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 数据模板中的WPF绑定不适用于自定义类_C#_Wpf_Xaml_Data Binding_Combobox - Fatal编程技术网

C# 数据模板中的WPF绑定不适用于自定义类

C# 数据模板中的WPF绑定不适用于自定义类,c#,wpf,xaml,data-binding,combobox,C#,Wpf,Xaml,Data Binding,Combobox,处理显示可用平铺背景列表的组合框。这只是一个简单的组合框,其中ItemSource设置为MapTileBackground对象的集合 MapTileBackground类完全由属性定义: public partial class MapTileBackground { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; }

处理显示可用平铺背景列表的组合框。这只是一个简单的组合框,其中ItemSource设置为MapTileBackground对象的集合

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; }
}
公共部分类MapTileBackground
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串说明{get;set;}
公共字节[]内容{get;set;}
公共可空颜色{get;set;}
公共int StrokeColor{get;set;}
公共字节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);
            }
        }
    }
}
公共类MapTileBackgroundPreview:形状
{
公共静态只读DependencyProperty SizeProperty=DependencyProperty.Register(“大小”、类型(点)、类型(MapTileBackgroundPreview));
公共静态只读DependencyProperty TileBackgroundProperty=DependencyProperty.Register(“TileBackground”、typeof(MapTileBackground)、typeof(MapTileBackgroundPreview));
公共MapTileBackgroundPreview()
{
布局=新六角布局(六角方向平面、新六角点(8,8)、新六角点(4,4));
尺寸=新点(8,8);
TileBackground=null;
}
私有十六进制布局;
受保护的替代几何图形定义几何图形
{
收到
{
var points=layout.HexCorners(0,0).ToArray();
var path=新路径图();
path.StartPoint=点[5].ToWin();
对于(变量i=0;i<6;i++)
添加(新线段(点[i].ToWin(),true));
var geo=新路径几何体();
geo.Figures.Add(路径);
返回geo;
}
}
公共点大小
{
收到
{
返回(点)GetValue(SizeProperty);
}
设置
{
设置值(SizeProperty,value);
layout.Size=value.ToHex();
layout.Origin=新的十六进制点(layout.Size.X/2,layout.Size.Y/2);
}
}
公共地图TileBackground TileBackground
{
收到
{
返回(MapTileBackground)GetValue(TileBackgroundProperty);
}
设置
{
SetValue(TileBackgroundProperty,值);
如果(值==null)
{
填充=画笔。透明;
笔划=画笔。黑色;
冲程厚度=1;
}
其他的
{
Stroke=value.Stroke();
StrokeThickness=value.StrokeThickness();
填充=值。填充(布局。方向);
}
}
}
}
布局只是屏幕像素坐标和六边形系统之间的转换工具。定义几何体只需添加六角体的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对象的集合),并将标签绑定到Name和Description

我的问题是形状总是绘制为空(如在TileBackground中为null),并且永远不会调用setter。名称标签和描述文本块的行为与预期一致(显示正确的文本)。在调试过程中,我在预览对象上创建了一个id属性,该属性反过来调用TileBackground Setter并将其绑定到id属性(避免当前对象绑定),同样,TileBackgroundId Setter永远不会被调用。我甚至添加了一个绑定到Id的新标签,以查看该标签是否起作用,并按预期显示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);
        }
    }

public static readonly dependencProperty TileBackgroundIdProperty=dependencProperty.Register(“TileBackgroundId”、typeof(int)、typeof(MapTileBackgroundPreview));
公共int TileBackgroundId
{
收到
{
返回(int)GetValue(TileBackgroundIdProperty);
}
设置
{
设置值(TileBackgroundIdProperty,值);
TileBackground=tOptileBackgroundTool.Get(值);
}
}
tmoptileBackgroundTool.Get()根据Id返回正确的对象

我还测试了数据模板外部的MapTileBackgroundPreview设置TileBackgroundId的实例


有什么想法吗?

由于WPF绑定引擎直接调用
GetValue
SetValue
方法,因此不应设置依赖项属性的CLR包装器的setter:

CLR包装器属性的getter和setter应该只分别调用
GetValue
SetValue
方法

如果要在设置dependency属性时执行某些操作,则应注册回调:

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

你能分享十六进制吗?或者在上面的代码中删除它?在这种情况下,Hex是一个名称空间别名。我不敢相信我在搜索答案或研究数据绑定时没有遇到这个问题,所以这完全是我的错。感谢你的快速回答。无论如何,我使用更改事件和将Id绑定到TileBackgroun时重新实现了所有三个属性