与 CollectionViewSource 绑定时,DesignTime 数据未显示在 Blend 中

Posted

技术标签:

【中文标题】与 CollectionViewSource 绑定时,DesignTime 数据未显示在 Blend 中【英文标题】:DesignTime data not showing in Blend when bound against CollectionViewSource 【发布时间】:2009-09-19 06:35:33 【问题描述】:

我有一个视图模型的数据模板,其中项目控件绑定到 CollectionViewSource(以启用 xaml 中的排序)。

<DataTemplate x:Key="equipmentDataTemplate">
    <Viewbox>
        <Viewbox.Resources>
            <CollectionViewSource x:Key="viewSource" Source="Binding Modules">
                <CollectionViewSource.SortDescriptions>
                    <scm:SortDescription PropertyName="ID" Direction="Ascending"/>
                </CollectionViewSource.SortDescriptions>
            </CollectionViewSource>
        </Viewbox.Resources>
        <ItemsControl ItemsSource="Binding Source=StaticResource viewSource" 
                      Height="DynamicResource equipmentHeight" 
                      ItemTemplate="StaticResource moduleDataTemplate">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </Viewbox>
</DataTemplate>

我还设置了 UserControl,所有这些都被定义为提供设计时数据

d:DataContext="x:Static vm:DesignTimeHelper.Equipment">

这基本上是一个静态属性,它为我提供了一个具有 ModuleViewModel (Equipment.Modules) 列表的 EquipmentViewModel。现在只要我绑定到 CollectionViewSource,设计时数据就不会显示在混合 3 中。当我直接绑定到 ViewModel 集合时

<ItemsControl ItemsSource="Binding Modules"

我可以看到设计时数据。知道我能做什么吗?

【问题讨论】:

有同样的问题。绑定 List 属性很好,但只要我绑定到绑定到该属性的 CollectionView,所有数据都会消失。 【参考方案1】:

做过(至少现在):)

这是我找到的解决方案。诀窍是覆盖 CollectionViewSource 设计时的源。我使用d:DesignSource 属性来使用另一个静态资源设计时间:

<Window.Resources>
    <CollectionViewSource x:Key="ViewSource"
            Source="Binding ModelProperty"
            d:DesignSource="x:Static MyProg:DesignTimeData.MyList">
        <!-- Contents -->
    </CollectionViewSource>
</Window.Resources>
    
<!-- No change to the using class -->
<ListBox ItemsSource="Binding Source=StaticResource ViewSource">
        
</ListBox>

【讨论】:

【参考方案2】:
    我不确定 x:Static 是否应该在 d:DataContext 中工作,我认为只有 d:DesignInstance 或 d:DesignData 可以。 您是否测试了设计时数据并确定确实填充了数据? 尝试在d:DesignInstance 中指定d:IsDesignTimeCreatable=True 属性。 虽然 this 是 Silverlight 特有的,但我相信它可能会给您一些提示。

它通常应该是这样的:

d:DataContext="d:DesignInstance Type=vm:EquipmentViewModel, IsDesignTimeCreatable=True"

您可以在运行时和设计时使用相同的 ViewModel,在您的 ViewModelBase 中创建一个 IsInDesignTime 属性并适当地返回数据。 示例:

private static bool? _isInDesignMode;
public static bool IsInDesignModeStatic

    get
    
        if (!_isInDesignMode.HasValue)
        
            var prop = DesignerProperties.IsInDesignModeProperty;
            _isInDesignMode
                = (bool)DependencyPropertyDescriptor
                .FromProperty(prop, typeof(FrameworkElement))
                .Metadata.DefaultValue;
        

        return _isInDesignMode.Value;
    

注意:我鼓励您使用StaticResources(而不是DynamicResources)用于在运行时不会更改的模板或样式。阅读this了解更多信息。

【讨论】:

【参考方案3】:

不确定这是否仍然相关...最近有一个类似的问题 - 我仍处于 WPF 学习曲线的某个位置,只是不太确定在哪里...

无论如何,这里是这样的场景:例如,我会在我的本地命名空间中的某处创建一个 ObservableCollection 类型的对象(为了简单起见)。

public class NodesCollection : ObservableCollection&lt;Nodes&gt;

然后从 Blend/Xaml 中,我可以轻松地“创建对象数据源”(从数据工具面板)并找到 NodesCollection 已显示并且可以选择。

接下来,Blend 将在 Xaml 文件顶部附近创建一个本地资源,类似于:

&lt;local:NodesCollection x:Key="NodesCollectionDataSource" d:IsDataSource="True" /&gt;

这样,您可以轻松地将列表框的ItemsSource 属性绑定到我们刚刚创建的数据源。例如,在“对象和时间线”工具面板中右键单击列表框,选择“数据将ItemsSource绑定到数据..”在弹出的对话框中,您会很容易看到NodesCollectionDataSource可用并且可以使用。

然而,我必须解决的问题来了……

在我目前正在阅读的一些书籍中,他们谈到在 Xaml 中创建一个 CollectionViewSource 可用于对其基础数据源进行排序/分组/过滤/导航。

第一个问题,我在 Blend 的任何地方都找不到 CollectionViewSource;所以唯一的选择是在 Xaml 中手动创建标签。

只需在资源块 (Xaml) 中键入 &lt;CollectionViewSource x:Key="cvsNodes" /&gt;,然后您就可以使用 Blend GUI 修改其他属性;例如设置基础 Source 属性和附加的 Sort 和 Group Descriptors(位于 Resources 工具面板下)。

现在是我们想要将 ListBox 的 ItemsSource 属性绑定到 CollectionViewSource 的部分。但是,您将无法使用 Blend GUI 找到该项目。因此,您必须手动键入绑定值。例如:

&lt;ListBox x:Name=.. ItemsSource="Binding Source=DynamicResource cvsNodes".. /&gt;

这行得通。但为了更简单,我们需要回到 Xaml 中的原始 CollectionViewSource 资源元素并添加一个附加属性:

&lt;CollectionViewSource x:Key="cvsNodes" Source=... d:IsDataSource="True"

d:IsDataSource="True" 可以让 Blend GUI 将资源识别为可用资源。

现在,如果我们从“属性”工具面板返回到 ListBox 的 ItemsSource 属性,我们应该能够从可用数据源列表中选择 cvsNodes

我希望这对可能得出与我相同结论的任何人有所帮助,即 Blend 和底层 Xaml 技术并未完全同步;而且 Blend 充其量只是生成 Xaml 的工具,而不是学习 Xaml 语言的替代品。

【讨论】:

也只是为了帮助回答原始问题;是的,这确实允许 Blend 在开发过程中显示示例数据。您需要做的就是在 ObjectCollection 类的构造函数中填充一些示例数据 - 在我的情况下,这将是 NodesCollection 的 ctor

以上是关于与 CollectionViewSource 绑定时,DesignTime 数据未显示在 Blend 中的主要内容,如果未能解决你的问题,请参考以下文章

在 CollectionViewSource 上触发过滤器

wpf数据绑定

CollectionViewSource,如何过​​滤数据?

在 ViewModel 中使用 CollectionViewSource 的正确方法

WPF:将列表动态绑定到(某些)对象的属性

WPF入门教程系列十八——WPF中的数据绑定