代码之家  ›  专栏  ›  技术社区  ›  Martin Brown

WPF设计时数据中的ReadOnlyObservableCollection<T>

  •  0
  • Martin Brown  · 技术社区  · 6 年前

    我有一个ViewModel,它的属性是 ReadOnlyObservableCollection . 定义如下:

    public class MyViewModel
    {
        private ObservableCollection<string> myProtectedCollection;
    
        public ReadOnlyObservableCollection<string> MyCollectionProperty { get; }
    
        public MyViewModel()
        {
            this.myProtectedCollection = new ObservableCollection<string>();
            this.MyCollectionProperty = new ReadOnlyObservableCollection<string>(this.myProtectedCollection);
            this.myProtectedCollection.Add("String1");
            this.myProtectedCollection.Add("String2");
            this.myProtectedCollection.Add("String3");
        }
    }
    

    然后我创建了一个名为测试数据.xaml并将生成操作设置为DesignData。因为我有这个:

    <local:MyViewModel 
        xmlns:local="clr-namespace:ScrapWpfApplication1"
        xmlns:system="clr-namespace:System;assembly=mscorlib">
        <local:MyViewModel.MyCollectionProperty>
            <system:String>String 1</system:String>
            <system:String>String 2</system:String>
        </local:MyViewModel.MyCollectionProperty>
    </local:MyViewModel>
    

    <Window x:Class="ScrapWpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:ScrapWpfApplication1"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525"
            d:DataContext="{d:DesignData Source=SampleData.xaml}">
        <ListBox ItemsSource="{Binding MyCollectionProperty}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Window>
    

    问题是它没有在visualstudio设计器中显示我的示例数据。如果我将视图模型中的集合更改为ObservableCollection,而不是ReadOnlyObservableCollection,那么它将作为Expected工作。

    我猜这是因为设计时数据系统正在创建一个伪ReadOnlyCollection,但是XAML无法填充它,因为它是readonly。

    0 回复  |  直到 6 年前
        1
  •  1
  •   mm8    6 年前

    有没有办法让设计类型的数据系统在不使视图模型的集合属性可写的情况下工作?

    是的,您可以创建另一个视图模型类,该类仅用于设计目的,具有 ObservableCollection<T> 属性,并设置设计时间 DataContext 这个实例的视图:

    d:DataContext="{d:DesignInstance Type=local:DesignTimeViewModel, IsDesignTimeCreatable=True}
    
        2
  •  1
  •   Martin Brown    6 年前

    我还没有找到一个完美的答案。但我终于做到了。

    而不是试图让设计数据系统模拟只读集合。我为这个集合创建了一组新的示例数据,并制作了主窗口.xaml你看这个。

    所以我的测试数据.xaml文件更改为仅此。实际上,它有更多的内容,但这只是这个问题的一个样本,所以它看起来相当空洞。

    <local:MyViewModel 
        xmlns:local="clr-namespace:ScrapWpfApplication1"
        xmlns:system="clr-namespace:System;assembly=mscorlib">
    </local:MyViewModel>
    

    其次,我创建了第二个测试数据文件TestDataArray.xaml文件里面有一个数组。确保将生成操作设置为DesignData。

    <x:Array Type="system:String"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
        xmlns:local="clr-namespace:ScrapWpfApplication1"
        xmlns:system="clr-namespace:System;assembly=mscorlib">
        <system:String>String 1</system:String>
        <system:String>String 2</system:String>
    </x:Array>
    

    <Window x:Class="ScrapWpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:ScrapWpfApplication1"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525"
            d:DataContext="{d:DesignData Source=SampleData.xaml}">
        <ListBox ItemsSource="{Binding}" DataContext="{Binding MyCollectionProperty}" d:DataContext="{d:DesignData Source=SampleDataArray.xaml}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Window>
    

    这适用于我的特定场景,但是如果示例数据被绑定到控件,并且ReadOnlyCollection被该控件内的某个对象读取,则会失败。