我最终编写了自己的扩展按钮。
它只是一个原型,仅用于一个子级别并且没有列排序。
但它可以扩展到其他用例。希望它可以帮助遇到同样问题的人。
我仍然期待得到任何改进的提示或想法。
谢谢!
Example outcome:
查看 (XAML)
<DataGrid Name="dgUsers" Grid.Row="0" Visibility="Visible" AutoGenerateColumns="False" ItemsSource="{Binding Users}"
CanUserAddRows="False" CanUserDeleteRows="False" CanUserSortColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Name="Expander" Width="Auto"></ColumnDefinition>
<ColumnDefinition Name="Content" Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" HorizontalAlignment="Left" Background="GhostWhite" BorderBrush="GhostWhite"
Visibility="{Binding ExpanderVisibility}"
Command="{Binding ExpandCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}}}"
Content="{Binding ExpanderSign}">
</Button>
<CheckBox Grid.Column="1" Margin="{Binding CheckboxMargin}"/>
<TextBlock Grid.Column="1" Text="{Binding Name}" Margin="{Binding JobNameMargin}"/>
</Grid>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Birthday" Binding="{Binding Birthday}" />
</DataGrid.Columns>
</DataGrid>
ViewModel (C#):
public class JobViewModel : BindableBase
{
private ObservableCollection<User> _users = new ObservableCollection<User>();
private static string _isExpandedSign = "^";
private static string _expandableSign = ">";
public JobViewModel()
{
var cori = ((new User() { Name = "Cori", Birthday = new DateTime(1982, 8, 10), ExpanderVisibility = "Hidden" }));
var penny = ((new User() { Name = "Penny", Birthday = new DateTime(1976, 7, 31), ExpanderVisibility = "Hidden" }));
var john = ((new User() { Id = 10, Name = "John Doe", Birthday = new DateTime(1971, 7, 23) } ));
var samy = ((new User() { Id = 20, Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) }));
var jane = ((new User() { Id = 30, Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) }));
var anny = ((new User() { Id = 40, Name = "Anny Doe", Birthday = new DateTime(1931, 1, 26) }));
john.AddChild(cori);
john.AddChild(penny);
jane.AddChild(cori);
jane.AddChild(penny);
anny.AddChild(cori);
anny.AddChild(penny);
_users.Add(john);
_users.Add(samy);
_users.Add(jane);
_users.Add(anny);
}
public class User : BindableBase
{
public int Id { get; set; }
public string ExpanderVisibility { get; set; }
public string CheckboxMargin { get; set; }
public string JobNameMargin { get; set; }
public bool IsExpanded { get; set; }
public string Name { get; set; }
public DateTime Birthday { get; set; }
public List<User> Children { get; set; }
public bool IsChild { get; set; }
public ICommand ExpandCommand { get; private set; }
public bool HasChildren()
{
return true;
}
public User(){
ExpandCommand = new DelegateCommand<DataGrid>(ExecuteExpandCommand);
ExpanderVisibility = "Hidden";
CheckboxMargin = "3,0,0,0";
JobNameMargin = "25,0,5,0";
Children = new List<User>();
}
public string ExpanderSign
{
get {
if (this.IsExpanded) return (_isExpandedSign);
else return (_expandableSign);
}
}
public void AddChild(User child)
{
child.CheckboxMargin = "23,0,0,0";
child.JobNameMargin = "45,0,5,0";
child.IsChild = true;
Children.Add(child);
ExpanderVisibility = "Visible";
}
private void ExecuteExpandCommand(DataGrid dg)
{
ObservableCollection<User> items = (ObservableCollection<User>)dg.ItemsSource;
int parentIndex=items.IndexOf(this);
if (!IsExpanded)
{
//expand
for (int i = 0; i < Children.Count; ++i)
{
items.Insert(parentIndex + 1 + i, Children.ElementAt(i));
}
}
else
{
int childrenCount = Children.Count;
for (int i=0; i< childrenCount; ++i)
{
if(parentIndex + 1 < items.Count && items.ElementAt(parentIndex + 1).IsChild) //just to be sure
{
items.RemoveAt(parentIndex + 1);
}
}
}
IsExpanded = !IsExpanded;
RaisePropertyChanged("ExpanderSign");
}
}
public ObservableCollection<User> Users
{
get { return _users; }
set { _users = value; }
}
}