我在这样定义的视图中有一个数据网格:
<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调试工具来确定动态绑定有什么问题?例如。如何在运行时检查这些动态创建的绑定以查看它们正在做什么(或者没有做到)?
代码中是否有明显的问题可能是问题的根源?
答案 0 :(得分:1)
Application.Current.TryFindResource("TypeIcon") as DataTemplate
原因是上面写的代码。 Application.Current.TryFindResource
仅在Application
实例的资源内查找资源。您在DataTemplate
内定义的DataGrid.Rsoures
。所以,有两种解决方案
Grid
获取资源(例如,将其作为ConverterParameter
传递)DataTemplate
定义从Grid.Resources
移至Application.Resources