调试破坏动态创建的DataGridTemplateColumn绑定

时间:2017-04-28 09:46:06

标签: c# wpf mvvm data-binding

我在这样定义的视图中有一个数据网格:

<DataGrid local:DataGridColumnsBehavior.BindableColumns="{Binding Path=Grid.DisplayedProperties, Converter={StaticResource DynamicColumnConverter}}"
          ItemsSource="{Binding Path=Grid.Items}" 
          AutoGenerateColumns="False"
          GridLinesVisibility="None" 
          SelectionUnit="CellOrRowHeader">
    <DataGrid.Resources>
        <DataTemplate x:Key="TypeIcon">
            <Image Height="16" Source="{Binding Path=Type, Converter={StaticResource TypeImageConverter}, Mode=OneWay}" />
        </DataTemplate>
        <DataTemplate DataType="dgv:InapplicablePropertyValueViewModel">
            <TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="DimGray"/>
        </DataTemplate>
        <DataTemplate DataType="dgv:ApplicablePropertyViewModel">
            <TextBlock Text="{Binding Path=Value}"/>
        </DataTemplate>
    </DataGrid.Resources>
</DataGrid>

“DataGridColumnsBehavior.BindableColumns”是附加行为的一种实现,它提供了从this answer获取的网格列的动态绑定。

因为我不希望我的ViewModel直接包含UI对象的集合(DataGridColumns),所以我编写了这个TypeConverter来根据我的ViewModel内容生成UI对象:

class DynamicColumnConverter : IValueConverter
{
    public Object Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
    {
        var propertyDefinitions = (IEnumerable<IPropertyDefinition>) value;

        Debug.Assert(propertyDefinitions != null);

        var columns = new ObservableCollection<DataGridColumn>
        {
            new DataGridTemplateColumn {CellTemplate = Application.Current.TryFindResource("TypeIcon") as DataTemplate},
            new DataGridTextColumn {Header = "Name", Binding = new Binding(nameof(Item.Name))},
            new DataGridTextColumn {Header = "Type", Binding = new Binding(nameof(Item.ShortType))},
            new DataGridTextColumn {Header = "Full Name", Binding = new Binding(nameof(Item.FullName))}
        };

        foreach (var propertyDefinition in propertyDefinitions)
        {
            var column = new DataGridTextColumn
            {
                Header = propertyDefinition.Name,
                Binding = new Binding($@"Properties[{propertyDefinition.Name}]")
            };
            columns.Add(column);
        }

        return columns;
    }

    public Object ConvertBack(Object value, Type targetType, Object parameter, CultureInfo culture)
    {
        return DependencyProperty.UnsetValue;
    }
}

网格项视图模型公开以下界面:

interface IGridItemViewModel
{
    public IReadOnlyDictionary<String, IPropertyViewModel> Properties { get; }
    public String Name {get; set;}
    public String FullName {get;}
    public String Type {get; set;}
    public String ShortType {get;}
}

因此所有绑定路径在运行时有效。我想。

转换器引用为Resources:

<Window.Resources>
    <local:DynamicColumnConverter x:Key="DynamicColumnConverter"/>    
    <local:TypeImageConverter x:Key="TypeImageConverter"/>
</Window.Resources>

所有列都显示在结果数据网格中,但图标未出现在第一列中,并且没有任何单元格值出现在foreach(var propertyDefinition in propertyDefinitions)循环中定义的任何列中。 GridItemViewModel 的Name,FullName和ShortType属性的动态绑定正在工作,这就是为什么我对绑定路径的正确性有一定信心。

我是一位经验不足的WPF开发人员,我在调试损坏的动态列时遇到问题。

我可以使用哪些Visual Studio调试工具来确定动态绑定有什么问题?例如。如何在运行时检查这些动态创建的绑定以查看它们正在做什么(或者没有做到)?

代码中是否有明显的问题可能是问题的根源?

1 个答案:

答案 0 :(得分:1)

Application.Current.TryFindResource("TypeIcon") as DataTemplate

原因是上面写的代码。 Application.Current.TryFindResource仅在Application实例的资源内查找资源。您在DataTemplate内定义的DataGrid.Rsoures。所以,有两种解决方案

  1. 以某种方式从Grid获取资源(例如,将其作为ConverterParameter传递)
  2. DataTemplate定义从Grid.Resources移至Application.Resources