Привязка к проектным данным в WPF

У меня есть окно WPF, содержащее ListBox. ItemsSource связан со свойством модели представления.

<Window x:Class="SimpleWpfApp.View.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"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding MainWindowViewModel, Source={StaticResource Locator}}">
  <DockPanel>
    <ListBox ItemsSource="{Binding SomeThings}" />
  </DockPanel>
</Window>

Свойство модели представления является наблюдаемой коллекцией пользовательского интерфейса; ISomeInterface. Интерфейс очень прост и реализован SomeClass, который дополнительно переопределяет ToString.

public class MainWindowViewModel
{
  public ObservableCollection<ISomeInterface> SomeThings
  {
    get
    {
      var list = new List<ISomeInterface>
      {
        new SomeClass {Value = "initialised"},
        new SomeClass {Value = "in"},
        new SomeClass {Value = "code"}
      };

      return new ObservableCollection<ISomeInterface>(list);
    }
  }
}

public interface ISomeInterface
{
  string Value { get; }
}

public class SomeClass : ISomeInterface
{
  public string Value { get; set; }

  public override string ToString() => Value;
}

Когда я просматриваю окно в Visual Studio 2015 или Blend, все происходит так, как ожидалось. Вызов ToString и заполнение ListBox.

Скриншот Blend

Я создал данные дизайна XAML, которые хочу использовать в режиме разработки. Я добавил данные дизайна в каталог с именем SampleData. Я добавляю оператор Datacontext в окно XAML, расположенное непосредственно под первым DataContext.

d:DataContext="{d:DesignData Source=/SampleData/Data.xaml}"

Это не работает Visual Studio и Blend сообщают "Файл или элемент проекта не найден" независимо от того, что я использую для исходного пути. Я пробовал /SampleData/Data.xaml, SampleData / Data.xaml,../SampleData/Data.xaml,./../SampleData/Data.xaml

Visual Studio и Blend находят Data.xaml только тогда, когда я перемещаю его из каталога SampleData в корень проекта. Затем я могу ссылаться на него, используя исходный путь /Data.xaml или Data.xaml. Если я использую Data.xaml без префикса /, тогда Visual Studio и Blend сообщают, что файл не может быть найден... но все равно его находят.

Мой первый вопрос... Могу ли я использовать примеры данных в подкаталоге? И если так, как?

После успешной ссылки на Data.xaml в корне проекта мое окно не вызывает переопределенную ToString, поэтому я получаю список отображаемых имен классов. Список имеет то же количество элементов, что и данные проекта, поэтому, похоже, он использует данные проекта.

Мой второй вопрос: почему переопределенная ToString не вызывается здесь, когда это происходит, если объекты создаются из кода?

Я знаю, что могу достичь желаемого результата, указав шаблон элемента.

<ListBox ItemsSource="{Binding SomeThings}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding Value}"/>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

Полный исходный код доступен для примера приложения на github.

https://github.com/DangerousDarlow/WpfDesignData

ОБНОВИТЬ

Спасибо jstreet за ответ. Я изменил свойства файла для data.xaml в подкаталоге и теперь могу использовать его в качестве проектных данных. Я думал, что попробовал это раньше, но я должен ошибаться.

Я до сих пор не вижу, чтобы ToString вызывали. Я попытался изменить свойство модели представления на List<object> а также List<ISomeInterface> но оба привели к вызову object.ToString; выводится отображением имени класса. Я, вероятно, перестану смотреть на этот момент, так как в любом случае я не собираюсь использовать ToString, я свяжусь со свойствами, которые я хочу отобразить. Хотя было бы хорошо объяснить разницу в поведении.

Я использую Visual Studio 2015 Community Edition.

1 ответ

Решение

Вот пример рабочего кода. Вы можете обратиться к этой статье - MSDN.

В частности, обратите внимание, как установить свойства для вашего Data.xaml файл (Dictionary1.xaml, в моем случае) в вашем проекте VS:

Также обратите внимание, как создать свой корневой объект, SomeThings (SomeClasses в моем случае):

Для коллекций корневым объектом может быть ArrayList или пользовательский тип, производный от коллекции или универсальной коллекции...

XAML:

<Window x:Class="WpfApplication277.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:WpfApplication277"
    d:DataContext="{d:DesignData Source=/SampleData/Dictionary1.xaml}"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <ListView ItemsSource="{Binding}"></ListView>
</Grid>

Dictionary1.xaml:

Щелкните правой кнопкой мыши SampleData папку в вашем проекте VS и выберите Add \ New Item \ WPF \ Resource Dictionary, замените его содержимое данными проекта. Это должно гарантировать, что ваши данные дизайна могут быть расположены в подпапке.

<m:SomeClasses xmlns:m="clr-namespace:WpfApplication277">
<m:SomeClass Value="design data 1">
</m:SomeClass>
<m:SomeClass Value="design data 2">
</m:SomeClass>
<m:SomeClass Value="design data 3">
</m:SomeClass>

SomeClasses: List<SomeClass> не работает!

public class SomeClasses : List<Object>
{
    public SomeClasses() { }
}

SomeClass:

public class SomeClass : ISomeInterface
{
    public string Value { get; set; }

    public override string ToString() => string.Format("ToString() : {0}",Value);
}

Обратите внимание, что ToString() определенно называется:

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