Вопрос

У меня есть файл mainwindow.xaml:

<Window.Resources>

  <CollectionViewSource x:Key="cvs" 
    Source="{Binding Source={StaticResource ResourceKey=DetailsCollection}}" />

  <CollectionViewSource x:Key="DetailScopes">
    <CollectionViewSource.Source>
      <ObjectDataProvider 
        MethodName="GetValues" 
        ObjectType="{x:Type system:Enum}">
        <ObjectDataProvider.MethodParameters>
          <x:Type TypeName="entities:DetailScope" />
        </ObjectDataProvider.MethodParameters>
      </ObjectDataProvider>
    </CollectionViewSource.Source>
  </CollectionViewSource>

  <DataTemplate x:Key="AccountDetail"
    DataType="{x:Type entities:AccountDetail}">
    <DockPanel>
      <ComboBox 
        DockPanel.Dock="Left" 
        ItemsSource="{Binding Source={StaticResource ResourceKey=DetailScopes}}" 
        SelectedItem="{Binding Path=Scope}">
        <ComboBox.ItemTemplate>
          <DataTemplate>
            <TextBlock 
              Text="{Binding Converter={StaticResource DetailScopeConverter}}" />
          </DataTemplate>
        </ComboBox.ItemTemplate>
      </ComboBox>
      <TextBox Text="{Binding Path=Value}" />
    </DockPanel>
  </DataTemplate>

</Window.Resources>

...

<ListBox 
  ItemTemplate="{StaticResource ResourceKey=AccountDetail}" 
  ItemsSource="{Binding Source={StaticResource ResourceKey=cvs}}" />

и его кодовый класс, где я определил фильтр для деталей Scopes:

public class MainWindow
{
    public MainWindow()
    {
        CollectionViewSource detailScopes;

        InitializeComponent();

        // Attach filter to the collection view source
        detailScopes = this.Resources["DetailScopes"] as CollectionViewSource;
        detailScopes.Filter += new FilterEventHandler(DetailScopesFilter);

        private void DetailScopesFilter(object sender, FilterEventArgs e)
        {
            DetailScope scope;

            scope = (DetailScope)e.Item;
            if (scope == DetailScope.Private ||
                scope == DetailScope.Business)
            {
                e.Accepted = true;
            }
            else
            {
                e.Accepted = false;
            }
        }
    }
}

Далее есть AccountDetail класс:

public class AccountDetail
{
  public string Value
  {
    get { return this.value; }
    set { this.value = value; }
  }
  public DetailScope Scope
  {
    get { return scope; }
    set { scope = value; }
  }

  private string value;
  private DetailScope scope;
}

Наконец, Enum:

public enum DetailScope
{
  Private, 
  Business, 
  Other
}

Когда я запускаю свой код, я получаю список в списке, заполненную кучей сведений с учетной записью, каждый из которых имеет собственную комбинированную коробку с выбранным объемом и текстовым ящиком с соответствующим значением. Проблема в том, что все выбранные значения в поле комбинированы соответствуют установленному набору охвата для последних введенных деталей и изменением любого из значений Combo Box обновляет все их, как если бы они все связаны с тем же деталями аккаунта.

Когда я вынуму ObjectDataProvider от CollectionViewSource Подробные кабины и связывают его непосредственно к коробке комбо ItemsSource в DataTemplate AccountDetail, проблема ушла. Тем не менее, мне нужно это внутри CollectionViewSource потому что я применяю его фильтрацию к нему, и я не могу применить фильтрацию к ObjectDataProvider.

Может кто-нибудь, пожалуйста, объясните, почему это происходит и как я на самом деле должен подключаться CollectionViewSource и ObjectDataProvider? Спасибо.

Это было полезно?

Решение

.

Проблема с вашим кодом в том, что Каждый Combobox использует один и тот же экземпляр CollectionViewsource; Это означает, что ресурс с ключом «Подробные кабины» поделился всем Combobox, поэтому всякий раз, когда вы выбираете одно значение из определенного Combobox, он автоматически выбирает одно и то же значение во всех Combobox. Это связано с тем, что базовая коллекция, которая передается, поддерживает отслеживание выбранного элемента, и поскольку он меняется на выборе из одного COBLOBOX, CollectionViewsource уведомляет изменение для всех Combobox.

Так что решение очень просто. Все, что вам нужно, чтобы сделать детали нерешительный.

Вот исправление:

<!-- Please note this x:Shared="False" just after x:Key="DetailsScopes" --->

<CollectionViewSource x:Key="DetailScopes"  x:Shared="False"> 
    <CollectionViewSource.Source>
      <ObjectDataProvider 
        MethodName="GetValues" 
        ObjectType="{x:Type system:Enum}">
        <ObjectDataProvider.MethodParameters>
          <x:Type TypeName="entities:DetailScope" />
        </ObjectDataProvider.MethodParameters>
      </ObjectDataProvider>
    </CollectionViewSource.Source>
  </CollectionViewSource>

Надеюсь, это решает вашу проблему!

Однако это решение приведет к другой проблеме. Позвольте мне процитировать что-то от MSDN, чтобы вы поймете, что X: Shared делает.

x: Общий атрибут

При установке в False изменяет поведение ресурсов WPF-Resource, так что запросы на приписываемый ресурс Создайте новый экземпляр для каждого запроса Вместо того, чтобы разделить тот же экземпляр для всех запросов.

Поскольку X: Shared Proseses создать новый экземпляр (новую копию) ресурса, когда вы пытаетесь получить доступ к ней, это означает, что метод обработчика фильтра прикреплен только к экземпляру, который вы попадаете в код, не все экземпляры.

Таким образом, чтобы правильно работать обработчик, вам нужно прикрепить обработчик от сама XAML, как это:

<!-- Now please note Filter="DetailsScopesFilter" --->

<CollectionViewSource x:Key="DetailScopes"  x:Shared="False"  Filter="DetailScopesFilter"> 
    <CollectionViewSource.Source>
      <ObjectDataProvider 
        MethodName="GetValues" 
        ObjectType="{x:Type system:Enum}">
        <ObjectDataProvider.MethodParameters>
          <x:Type TypeName="entities:DetailScope" />
        </ObjectDataProvider.MethodParameters>
      </ObjectDataProvider>
    </CollectionViewSource.Source>
  </CollectionViewSource>

Надеюсь, это решает все ваши проблемы. Дайте мне знать, если вы все еще сталкиваетесь. :-)

О, кстати, следующий код не нужен больше. Поэтому, пожалуйста, удалите его.

    // Attach filter to the collection view source
    detailScopes = this.Resources["DetailScopes"] as CollectionViewSource;
    detailScopes.Filter += new FilterEventHandler(DetailScopesFilter);

.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top