XAML:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Persons}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Id}" />
<DataGridTextColumn Binding="{Binding Name}" />
<DataGridTemplateColumn Header="Name1" CellEditingTemplate ="{Binding Path=Cars, Converter={StaticResource myConverter}}" />
</DataGrid.Columns>
</DataGrid>
转换器:
public class myConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is ObservableCollection<Car> test)
{
//create the data template
DataTemplate cardLayout = new DataTemplate();
foreach (var t in test)
{
//set up the stack panel
FrameworkElementFactory spFactory = new FrameworkElementFactory(typeof(StackPanel));
spFactory.Name = "myComboFactory";
spFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
//set up the textblock
FrameworkElementFactory childFactory;
childFactory = new FrameworkElementFactory(typeof(TextBlock));
childFactory.SetValue(TextBlock.TextProperty, t.Color);
spFactory.AppendChild(childFactory);
//set up the textblock
childFactory = new FrameworkElementFactory(typeof(TextBlock));
childFactory.SetValue(TextBlock.TextProperty, t.Speed);
spFactory.AppendChild(childFactory);
//set the visual tree of the data template
cardLayout.VisualTree = spFactory;
}
return cardLayout;
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
//Will do.
return DependencyProperty.UnsetValue;
}
}
C#:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public ObservableCollection<Car> Cars { get; set; }
}
public class Car
{
public string Color { get; set; }
public int Speed { get; set; }
}
public class ViewModelsWindow2
{
public ObservableCollection<Person> Persons { get; }
public ViewModelsWindow2()
{
Persons = new ObservableCollection<Person>();
Persons.Add(new Person() { Id = 177, Name = "John", Cars = new ObservableCollection<Car>() { new Car() { Color = "Green", Speed = 360 } } });
}
}
我想用一些动态TextBox(例如两个TextBlocks)创建自己的DataGridTemplateColumn。我想通过转换器执行此操作,因为我需要双向使用DataGridTemplateColumn。我还没有为ConvertBack编写代码。 每行的文本框数量会有所不同。
但是我有一个问题。该转换器不能由WPF执行。我在Convert的开始处设置了断点,并且代码没有停止。
请帮我决定这个问题。我该怎么办?
就是这样。它是静态的,但我想动态。
我可能会向Car添加属性,并且该人可能有两辆,三辆...颜色和速度不同的汽车。
数据将由用户编辑。
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Persons}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Id}" />
<DataGridTextColumn Binding="{Binding Name}" />
<DataGridTemplateColumn Header="Name1" CellEditingTemplate ="{Binding Path=Cars, Converter={StaticResource myConverter}}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="Green"/>
<TextBox Text="360"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBox Text="Red"/>
<TextBox Text="360"/>
...
</StackPanel>
...
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
更新:
我将Converter定义为:
xmlns:vm="clr-namespace:WpfApp1.ViewModels"
...
<Window.Resources>
<ResourceDictionary>
<vm:myConverter x:Key="myConverter" />
</ResourceDictionary>
</Window.Resources>
<Window.DataContext>
<vm:ViewModelsWindow2 />
</Window.DataContext>
答案 0 :(得分:1)
您不能像这样绑定到CellEditingTemplate
属性。 DataGridTemplateColumn
不是FrameworkElement
,因此它没有要绑定的任何DataContext
。
您应该做的是使用CellEditingTemplateSelector
:
public class Selector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
Person person = item as Person;
if(person != null && person.Cars != null)
{
DataTemplate cardLayout = new DataTemplate();
foreach (Car car in person.Cars)
{
//build your template..
}
return cardLayout;
}
return null;
}
}
XAML:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Persons}">
<DataGrid.Resources>
<local:Selector x:Key="selector" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Id}" />
<DataGridTextColumn Binding="{Binding Name}" />
<DataGridTemplateColumn Header="Name1" IsReadOnly="False" CellEditingTemplateSelector="{StaticResource selector}" />
</DataGrid.Columns>
</DataGrid>