DesignTime data not showing in Blend when bound against CollectionViewSource

后端 未结 3 1009
名媛妹妹
名媛妹妹 2021-02-07 09:55

I have a datatemplate for a viewmodel where an itemscontrol is bound against a CollectionViewSource (to enable sorting in xaml).



        
相关标签:
3条回答
  • 2021-02-07 10:40

    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.

    0 讨论(0)
  • 2021-02-07 11:00

    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.Resource>
        <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>
    
    0 讨论(0)
  • 2021-02-07 11:02
    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.

    0 讨论(0)
提交回复
热议问题