Подтвердить что ты не робот

Почему CompositeCollection не Freezable?

Я пишу приложение с использованием шаблона MVVM. Я предоставляю данные своему представлению, установив свое свойство DataContext в экземпляр моего ViewModel. Вообще я просто использую Binding оттуда и иду по своему пути.

В последнее время я попытался реализовать ComboBox с "лишним" элементом за пределами коллекции, которую предоставляет ViewModel, которая гласит "Выбрать элемент".

<ComboBox>    
    <ComboBox.ItemsSource>    
        <CompositeCollection>
           <ComboBoxItem IsEnabled="False">Select Item</ComboBoxItem>
           <CollectionContainer Collection="{Binding MyItemsCollection}" />    
        </CompositeCollection>
    </ComboBox.ItemsSource>
</ComboBox>

Проблема заключается в том, что CompositeCollection не является Freezable: Обзор замороженных объектов. Это приводит к появлению только статического ComboBoxItem и ни одного из результатов моего привязывающего выражения.

Моя первоначальная реакция на проблему состояла в том, чтобы просто реализовать мою собственную версию CompositeCollection, которая была Freezable. Это, однако, вызывает следующий вопрос:

Почему не CompositeCollection не является Freezable в первую очередь?

Моя забота состоит в том, что в целом эти решения принимаются по какой-то причине, и я не чувствую, что достаточно знаю о Freezable, чтобы сказать, почему они не наследовали ее. Я знаю, что могу реализовать эту коллекцию, но я обеспокоен тем, что если я это сделаю, будет заметная разница в производительности.

Любая помощь будет оценена по достоинству. Спасибо!

Также: обратите внимание, что я понимаю, что могу вставить Null или другое специальное значение и предоставить и шаблон или valueconverter делать то, что я хочу. Это не вопрос, который меня интересует... только вопрос, выделенный жирным шрифтом выше.

Update:

После некоторых дальнейших исследований, вызванных комментарием АрсенаМкрта, я убежден, что это на самом деле является надзором. Свидетельством является следующее:

  • Существует коллекция, которая является замораживаемой под названием FreezableCollection<T>. Я не создаю CollectionViews, что делает его неприемлемым для моих нужд.
  • Сэм Бент из MSFT говорит так же в приведенной выше ссылке. Я пока не могу найти контактную информацию, но я планирую обсудить это с ним, если у меня появится такая возможность.

Мой текущий план решить эту проблему - создать новую коллекцию со свойствами CompositeCollection и FreezableCollection<T>. Я не знаю, будет ли это работать, но я думаю о чем-то вроде этого:

public class BindableCompositeCollection : FreezableCollection<object>, ICollectionViewFactory

Если у кого-то есть лучший вариант, я бы хотел его услышать!

4b9b3361

Ответ 1

Я просто пробовал это сегодня вечером:

public class State
{
    public string Code { get; set; }
    public string Name { get; set; }
}

public class MyWindowViewModel
{
    ObservableCollection<State> _states = new ObservableCollection<State>
    {
        new State { Code = "FL", Name = "Florida" },
        new State { Code = "CA", Name = "California" },
    };

    public ObservableCollection<State> States
    {
        get
        {
            return _states;
        }
    }
}
<Window x:Class="WpfApplication1.MyWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:app="clr-namespace:WpfApplication1"
        Title="Window1"
        Height="300"
        Width="300">

  <Window.Resources>
    <app:ServiceLocator x:Key="Locator" />
  </Window.Resources>

  <StackPanel>
    <ComboBox x:Name="TestCombo" SelectedIndex="0" DisplayMemberPath="Name" SelectedValuePath="Code">
      <ComboBox.ItemsSource>
        <CompositeCollection>
          <app:State Code="" Name="Select a state..." />
          <app:State Code="TX" Name="Texas" />
          <CollectionContainer Collection="{Binding Source={StaticResource Locator}, Path=MyWindowViewModel.States}" />
        </CompositeCollection>
      </ComboBox.ItemsSource>
    </ComboBox>
  </StackPanel>
</Window>

Ключевым моментом здесь является создание экземпляра вашего локатора сервисов в качестве статического ресурса, затем переход через него, чтобы добраться до вашей модели просмотра. Локатор сервисов может подключаться к экземплярам ViewModel с использованием Unity или любого другого DI, который вы хотите.

Edit:

На самом деле в моем приложении silverlight я создаю локатор службы как статический resoure в App.xaml, а затем привязываю другие мои UserControls/Windows/Pages DataContext к свойству ViewModel локатора службы. Он должен работать одинаково для комбинированных блоков, хотя даже если локатор службы создается в ресурсах App.xaml. Мне жаль, что не было версии Silverlight CompositeCollection, которую я мог бы использовать. Это отлично подойдет для приложения, над которым я работаю.: (