将 child 个节点绑定到 CollectionViewSource
Binding child nodes to CollectionViewSource
所以这是我的数据结构:
MyViewModel
Docs (ObservableCollection<Doc>)
Specs (ObservableCollection<Spec>)
即ViewModel 有一个名为 Docs
的 ObservableCollection
,它是 Doc
object 的集合,而每个 Doc
object 都有一个集合Spec
object秒。名为 position
的 属性(在 Doc 和 Spec 类 中均可用)存储每个 doc/spec.
的逻辑位置
我现在需要将此结构绑定到 TreeView
。我需要始终保持 Docs 和 Specs 排序(TreeView 支持 drag-n-drop 重新排列节点),因此直接绑定在这里不起作用。
因此我使用 CollectionViewSource
在运行时执行排序。
<CollectionViewSource x:Key="DocumentsCVS" Source="{Binding Docs}">
<CollectionViewSource.SortDescriptions>
<componentmodel:SortDescription PropertyName="position" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
并在我的 TreeView 中使用它:
<TreeView ItemsSource="{Binding Source={StaticResource DocumentsCVS}}">
到目前为止一切顺利。 TreeView 显示我的文档已排序。
但从这里开始,事情就变得扑朔迷离了。 How/where 我要为我的规格创建 CollectionViewSource
吗?我尝试在 HierarchicalDataTemplate
:
中这样做
<HierarchicalDataTemplate>
<HierarchicalDataTemplate.ItemsSource>
<Binding>
<Binding.Source>
<CollectionViewSource Source="{Binding Specs}">
<CollectionViewSource.SortDescriptions>
<componentmodel:SortDescription PropertyName="position" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Binding.Source>
</Binding>
</HierarchicalDataTemplate.ItemsSource>
</HierarchicalDataTemplate>
但这行不通。 TreeView
中只列出了 Docs,里面没有 children。我的直觉是 CollectionViewSource
可能不和 parent TreeViewItem
.
住在同一个 DataContext
或者这是别的东西?
编辑
这是我的 TreeView 的完整 XAML:
<TreeView ItemsSource="{Binding Source={StaticResource DocumentsCVS}}"
PresentationTraceSources.TraceLevel="High">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type vm:DocumentVM}">
<HierarchicalDataTemplate.ItemsSource>
<Binding>
<Binding.Source>
<CollectionViewSource Source="{Binding Specs}">
<CollectionViewSource.SortDescriptions>
<componentmodel:SortDescription PropertyName="position" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Binding.Source>
</Binding>
</HierarchicalDataTemplate.ItemsSource>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate DataType="{x:Type vm:SpecVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<fa:ImageAwesome Grid.Column="0" Icon="PuzzlePiece" Width="16" Margin="3,3,6,3" Foreground="Orange" />
<Label Grid.Column="1" Content="{Binding name}" />
</Grid>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<fa:ImageAwesome Icon="FileWordOutline" Height="16" Margin="3,3,6,3" Foreground="Crimson" />
<Label Grid.Column="1" Content="{Binding name}" />
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<CollectionViewSource Source="{Binding Specs}">
Source 上的绑定不知道去哪里寻找 DataContext(没有 "framework mentor")。我已经解决了这个问题。我找不到一个地方来定义 CollectionViewSource,它从模板继承 DataContext。
我确实找到了解决办法。
C#
public class SortConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var view = CollectionViewSource.GetDefaultView(value);
view.SortDescriptions.Add(new SortDescription((string)parameter, ListSortDirection.Ascending));
return view;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML
<HierarchicalDataTemplate
DataType="{x:Type vm:DocumentVM}"
ItemsSource="{Binding Specs, Converter={StaticResource SortConverter}, ConverterParameter=position}"
>
这可以通过为转换器提供多个 PropertyName/SortDirection 属性或一组 SortDescriptions 来变得更有用。您可以将其设为 MarkupExtension。您也可以只在视图模型中创建集合视图 属性。
所以这是我的数据结构:
MyViewModel
Docs (ObservableCollection<Doc>)
Specs (ObservableCollection<Spec>)
即ViewModel 有一个名为 Docs
的 ObservableCollection
,它是 Doc
object 的集合,而每个 Doc
object 都有一个集合Spec
object秒。名为 position
的 属性(在 Doc 和 Spec 类 中均可用)存储每个 doc/spec.
我现在需要将此结构绑定到 TreeView
。我需要始终保持 Docs 和 Specs 排序(TreeView 支持 drag-n-drop 重新排列节点),因此直接绑定在这里不起作用。
因此我使用 CollectionViewSource
在运行时执行排序。
<CollectionViewSource x:Key="DocumentsCVS" Source="{Binding Docs}">
<CollectionViewSource.SortDescriptions>
<componentmodel:SortDescription PropertyName="position" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
并在我的 TreeView 中使用它:
<TreeView ItemsSource="{Binding Source={StaticResource DocumentsCVS}}">
到目前为止一切顺利。 TreeView 显示我的文档已排序。
但从这里开始,事情就变得扑朔迷离了。 How/where 我要为我的规格创建 CollectionViewSource
吗?我尝试在 HierarchicalDataTemplate
:
<HierarchicalDataTemplate>
<HierarchicalDataTemplate.ItemsSource>
<Binding>
<Binding.Source>
<CollectionViewSource Source="{Binding Specs}">
<CollectionViewSource.SortDescriptions>
<componentmodel:SortDescription PropertyName="position" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Binding.Source>
</Binding>
</HierarchicalDataTemplate.ItemsSource>
</HierarchicalDataTemplate>
但这行不通。 TreeView
中只列出了 Docs,里面没有 children。我的直觉是 CollectionViewSource
可能不和 parent TreeViewItem
.
DataContext
或者这是别的东西?
编辑
这是我的 TreeView 的完整 XAML:
<TreeView ItemsSource="{Binding Source={StaticResource DocumentsCVS}}"
PresentationTraceSources.TraceLevel="High">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type vm:DocumentVM}">
<HierarchicalDataTemplate.ItemsSource>
<Binding>
<Binding.Source>
<CollectionViewSource Source="{Binding Specs}">
<CollectionViewSource.SortDescriptions>
<componentmodel:SortDescription PropertyName="position" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Binding.Source>
</Binding>
</HierarchicalDataTemplate.ItemsSource>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate DataType="{x:Type vm:SpecVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<fa:ImageAwesome Grid.Column="0" Icon="PuzzlePiece" Width="16" Margin="3,3,6,3" Foreground="Orange" />
<Label Grid.Column="1" Content="{Binding name}" />
</Grid>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<fa:ImageAwesome Icon="FileWordOutline" Height="16" Margin="3,3,6,3" Foreground="Crimson" />
<Label Grid.Column="1" Content="{Binding name}" />
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<CollectionViewSource Source="{Binding Specs}">
Source 上的绑定不知道去哪里寻找 DataContext(没有 "framework mentor")。我已经解决了这个问题。我找不到一个地方来定义 CollectionViewSource,它从模板继承 DataContext。
我确实找到了解决办法。
C#
public class SortConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var view = CollectionViewSource.GetDefaultView(value);
view.SortDescriptions.Add(new SortDescription((string)parameter, ListSortDirection.Ascending));
return view;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML
<HierarchicalDataTemplate
DataType="{x:Type vm:DocumentVM}"
ItemsSource="{Binding Specs, Converter={StaticResource SortConverter}, ConverterParameter=position}"
>
这可以通过为转换器提供多个 PropertyName/SortDirection 属性或一组 SortDescriptions 来变得更有用。您可以将其设为 MarkupExtension。您也可以只在视图模型中创建集合视图 属性。