为什么 CompositeCollection 不可冻结? [英] Why is CompositeCollection not Freezable?

查看:27
本文介绍了为什么 CompositeCollection 不可冻结?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 MVVM 模式编写应用程序.我通过将视图的 DataContext 属性设置为我的 ViewModel 实例来向我的视图提供数据.通常我只是从那里使用 Binding 并按照我的方式去做.

I am writing an application using the MVVM pattern. I am providing data to my view by setting my view's DataContext property to an instance of my ViewModel. Generally I just use Binding from there and go about my way.

最近,我尝试实现一个带有额外"功能的 ComboBox我的 ViewModel 提供的集合之外的元素,上面写着选择项目".

Recently, I tried to implement a ComboBox with an "extra" element beyond the collection my ViewModel provides that says "Select Item".

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

问题是,CompositeCollection 不是 Freezable:Freezable 对象概述.这只会导致静态 ComboBoxItem 出现,而​​没有任何来自我的绑定表达式的结果.

The problem is, CompositeCollection is not a Freezable: Freezable Objects Overview. This causes only the static ComboBoxItem to appear and none of the results from my binding expression.

我对这个问题的最初反应是实现我自己的 CompositeCollection 版本, Freezable.不过,这引出了以下问题:

My initial reaction to the problem was to just implement my own version of CompositeCollection that was Freezable. This, though, begs the following question:

为什么 CompositeCollection 首先不是 Freezable?

我担心的是,通常做出这些决定是有原因的,我觉得我对 Freezable 了解不够,无法说明为什么他们没有继承自它.我知道我可以实现这个集合,但我担心如果我这样做了,性能上会有明显的差异.

My concern is that generally these decisions are made for a reason and I don't feel I know enough about Freezable to say why they didn't inherit from it. I know I can implement this collection, but I'm concerned there will be a measurable difference in performance if I do.

任何帮助将不胜感激.谢谢!

Any help would be appreciated. Thanks!

另外:请注意,我意识到我可以插入 Null 或其他一些特殊值,并提供模板或 valueconverter 来做我想做的事.这不是我感兴趣的问题……只有上面粗体的问题.

更新:

根据 ArsenMkrt 的评论进行进一步研究后,我相信这实际上是一个疏忽.证据是这样的:

After some further research brought on by ArsenMkrt's comment, I'm led to believe this was actually an oversight. The evidence is this:

  1. 有一个可冻结的集合,称为FreezableCollection.它不生成 CollectionViews,这使得它直接不适合我的需求.
  2. MSFT 的 Sam Bent 在上面的链接中说了同样多的话.我还没有找到他的联系信息,但如果有机会,我打算与他讨论这个问题.
  1. There is a collection that is freezable called FreezableCollection<T>. It does not produce CollectionViews, which makes it inappropriate for my needs directly.
  2. Sam Bent of MSFT says as much in the above link. I cannot find contact information for him yet, but I plan on discussing this with him if I get the chance.

我目前解决这个问题的计划是创建一个具有 CompositeCollection 和 FreezableCollection 属性的新集合.我不知道它是否会起作用,但我正在考虑这样的事情:

My current plan to get around this problem is to create a new collection with the properties of CompositeCollection and FreezableCollection<T>. I don't know if it'll work yet, but I'm thinking about something like this:

public class BindableCompositeCollection : FreezableCollection<object>, ICollectionViewFactory

如果有人有更好的选择,我想听听!

If anyone has a better option, I'd like to hear it!

推荐答案

我今晚刚试过:

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>

这里的关键是将您的服务定位器的实例创建为静态资源,然后通过它到达您的视图模型.服务定位器可以使用 Unity 或您想要的任何 DI 连接到 ViewModel 的实例.

The key here is to create an instance of your service locator as a static resource then go through it to get to your viewmodel. The service locator can wire up to instances of the ViewModel using Unity or whatever DI you want.

实际上,在我的 Silverlight 应用程序中,我将服务定位器创建为 App.xaml 中的静态资源,然后将我的其他 UserControls/Windows/Pages DataContext 绑定到服务定位器的 ViewModel 属性.即使服务定位器在 App.xaml 的资源中实例化,它仍然应该以相同的方式用于组合框.我希望有一个我可以使用的 Silverlight 版本的 CompositeCollection.这对我正在开发的应用程序非常有用.:(

Actually in my silverlight app I create the service locator as a static resoure in the App.xaml and then bind my other UserControls/Windows/Pages DataContext to a ViewModel property of the service locator. It should still work the same way for the combo boxes though even if the service locator is instantiated in the App.xaml's resources. I wish there was a silverlight version of CompositeCollection that I could use. This would work great for the app I'm working on. :(

这篇关于为什么 CompositeCollection 不可冻结?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆