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

发布于 2024-08-05 08:53:39 字数 1536 浏览 6 评论 0 原文

我有一个视图模型的数据模板,其中 itemscontrol 与 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}">

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

<ItemsControl ItemsSource="{Binding Modules}"

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

I have a datatemplate for a viewmodel where an itemscontrol is bound against a CollectionViewSource (to enable sorting in 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>

I have also setup the UserControl where all of this is defined to provide designtime data

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

This is basically a static property that gives me an EquipmentViewModel that has a list of ModuleViewModels (Equipment.Modules). Now as long as I bind to the CollectionViewSource the designtime data does not show up in blend 3. When I bind to the ViewModel collection directly

<ItemsControl ItemsSource="{Binding Modules}"

I can see the designtime data. Any idea what I could do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

还如梦归 2024-08-12 08:53:39

已经这样做了(至少现在):)

这是我找到的解决方案。诀窍是重写 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>

Been there done that (now at least) :)

This is the solution I've found. The trick is to override the source for the CollectionViewSource designtime. I use the d:DesignSource property to use another static resource designtime:

<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>
ゝ杯具 2024-08-12 08:53:39
  1. 我不确定 x:Static 是否应该在 d:DataContext 中工作,我认为只有 d:DesignInstance 或 d:DesignData 可以。
  2. 您是否测试了设计时数据并确定确实充满了数据?
  3. 尝试在 d:DesignInstance 中指定 d:IsDesignTimeCreatable=True 属性。
  4. 虽然是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)。请阅读本文了解更多信息。

  1. I am not sure x:Static is supposed to work in d:DataContext, I think only d:DesignInstance or d:DesignData could.
  2. Did you test the design time data and sure that indeed filled with data?
  3. Try specifying the d:IsDesignTimeCreatable=True property in the d:DesignInstance.
  4. Although this is Silverlight specific I am sure it might give you some hint.

It should generally look like this:

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

You could use the same ViewModel for both runtime and designtime, make a IsInDesignTime property in you ViewModelBase and return data appropriately.
Example:

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;
    }
}

Note: I would encourage you to use StaticResources (rather than DynamicResources) for templates or styles that are not meant to change at runtime. Read this for more info.

黯淡〆 2024-08-12 08:53:39

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

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

public class NodesCollection : ObservableCollection; { }

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

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

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

但是我必须解决的问题来了...

在我目前正在阅读的一些书中,他们讨论了在 Xaml 中创建可用于排序/分组/过滤/导航的 CollectionViewSource其底层数据源。

第一个问题,我在 Blend 中找不到 CollectionViewSource;因此唯一的选择是在 Xaml 中手动创建标签。

只需在资源块 (Xaml) 中键入 ,然后您就可以使用 Blend GUI 修改其他属性;例如,设置基础源属性和附加排序和组描述符(可在资源工具面板下找到)。

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

这有效。但为了使其更容易,我们需要返回到 Xaml 中的原始 CollectionViewSource 资源元素并添加一个附加属性:

d:IsDataSource="True" 的技巧是让 Blend GUI 识别出该资源可供使用。

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

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

Not sure if this is still relevant... recently had a similar issue - I'm still somewhere on the WPF learning curve, just not quite sure where...

Anyways, here's the scenario: I would create an object of type ObservableCollection somewhere in my local namespace (to keep things simple), for example..

public class NodesCollection : ObservableCollection<Nodes> { }

Then from Blend/Xaml, I can easily "Create Object Data Source" (from Data tools panel) and find NodesCollection is shown and can be selected.

Next, Blend will create a local resource near the top of the Xaml file, similar to:

<local:NodesCollection x:Key="NodesCollectionDataSource" d:IsDataSource="True" />

With this, you can easily bind the ItemsSource property of a listbox to the datasource we have just created. For example, right-click on your listbox from "Objects and Timeline" tools panel and select "Data bind ItemsSource to Data.." In the popup dialog box, you will easily see NodesCollectionDataSource is available and can be used.

However here comes the issues I had to resolve...

In some books I'm reading at the moment, they talk about creating a CollectionViewSource in Xaml that can be used for sorting/grouping/filtering/navigating its underlying data source.

First issue, I can't find CollectionViewSource anywhere in Blend; so the only option is to create the tag in Xaml manually.

Simply type <CollectionViewSource x:Key="cvsNodes" /> within the Resources block (Xaml) and from there, you can modify additional properties using the Blend GUI; for example setting the underlying Source property and additional Sort and Group Descriptors (found under the Resources tools panel).

Now comes the part where we want to bind the ListBox's ItemsSource property to the CollectionViewSource. However you wont be able to find that item using the Blend GUI. Therefore you must type the binding value manually. For example:

<ListBox x:Name=.. ItemsSource="{Binding Source={DynamicResource cvsNodes}}".. />

This works. But to make it even easier, we need to go back to the original CollectionViewSource resource element in Xaml and add an additional attribute:

<CollectionViewSource x:Key="cvsNodes" Source=... d:IsDataSource="True"

The d:IsDataSource="True" does the trick of having Blend GUI recognize that resource as available to be used.

Now if we go back to the ListBox's ItemsSource property from the Properties tools panel, we should be able to select cvsNodes from the list of available Data sources.

I hope this helps anyone who may have come to the same conclusion as me, which is that Blend and the underlying Xaml technology isn't completely synchronized; and that Blend is at best a tool for generating the Xaml, not a replacement for learning the Xaml language.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文