ReadOnlyObservableCollection<T> в данных времени разработки WPF

У меня есть 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 с именем TestData.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>

Наконец у меня есть MainWindow.xaml со следующим:

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

Проблема в том, что это не показывает мои образцы данных в конструкторе Visual Studio. Если я изменю коллекцию в моей модели представления на ObservableCollection вместо ReadOnlyObservableCollection, то она будет работать как указано.

Я предполагаю, что это потому, что система данных времени разработки создает фиктивную коллекцию ReadOnlyCollection, но XAML не может заполнить ее, потому что она доступна только для чтения.

Есть ли способ заставить систему данных типа проекта работать без записи свойства коллекции моей модели представления?

2 ответа

Есть ли способ заставить систему данных типа проекта работать без записи свойства коллекции моей модели представления?

Да, вы можете создать другой класс модели представления, который будет использоваться только в целях проектирования, с ObservableCollection<T> свойство и установить время проектирования DataContext вид на экземпляр этого:

d:DataContext="{d:DesignInstance Type=local:DesignTimeViewModel, IsDesignTimeCreatable=True}

Я не видел идеального ответа на это. Но это то, что я наконец-то сделал.

Вместо того, чтобы пытаться заставить проектную систему данных издеваться над коллекцией только для чтения. Я создал новый набор примеров данных только для коллекции и заставил MainWindow.xaml взглянуть на это.

Так что мой файл TestData.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>

Наконец я изменил свой файл MainWindow.xaml на это. Обратите внимание на изменение привязки на

<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 читался чем-то внутри этого элемента управления.

Другие вопросы по тегам