ItemsControl отображает только один элемент управления при получении нескольких элементов управления с тем же ключом через TryFindResource - PullRequest
0 голосов
/ 23 февраля 2012

Во-первых, мой сценарий. У меня есть ViewModel с открытым свойством Items типа ObservableCollection<UserControl>, который содержит пользовательские элементы управления, которые я хочу отображать с помощью <ItemsControl ItemsSource="{Binding Items}" />.

Я получаю UserControls, используя Application.Current.TryFindResource("ControlKey") as UserControl. Когда у каждого ресурса свой x:Key, все работает нормально. Однако, когда я добавляю больше UserControls к Items с тем же x:Key, ItemsControl отображает только один из UserControls с идентичным x:Key, даже если все пользовательские элементы управления присутствуют в Items .

Например, я добавляю элементы в коллекцию следующим образом:

Items.Add(Application.Current.TryFindResource("Filter1") as UserControl);
Items.Add(Application.Current.TryFindResource("Filter1") as UserControl);
Items.Add(Application.Current.TryFindResource("Filter2") as UserControl);

В ItemsControl отображаются только два элемента управления, один с x: ключ «Filter1» и один с «Filter2». Второй UserControl с x: ключ «Filter1» не отображается.

Чего мне не хватает? Большое спасибо.

1 Ответ

1 голос
/ 23 февраля 2012

Каждый элемент в логическом дереве может использоваться только один раз.Вы пытаетесь использовать один и тот же элемент дважды.Посмотрите на следующий пример:

<Window x:Class="SO.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Button x:Key="btn">Hello</Button>
    </Window.Resources>
    <StackPanel>
        <ContentControl Content="{StaticResource btn}" />
        <ContentControl Content="{StaticResource btn}" />
    </StackPanel>
</Window>

Если вы попытаетесь запустить этот код, вы получите исключение при назначении свойства Content.Внутреннее исключение скажет вам, что элемент уже размещен где-то еще в дереве.

Вы должны создать новый экземпляр UserControl для каждого элемента в коллекции (подсказка: ключевое слово 'new' должно где-то использоваться).

РЕДАКТИРОВАТЬ (ответ на комментарий @Jan): @Jan, используя отражение, вы можете создавать новые экземпляры объекта заданного типа - это не предпочтительный дизайн.Забудьте о размещении экземпляров вашего пользовательского элемента управления в словаре приложения.Просто определите классы.Тогда вместо:

Items.Add(Application.Current.TryFindResource("Filter1") as UserControl);
Items.Add(Application.Current.TryFindResource("Filter1") as UserControl);

просто сделайте:

Items.Add( new Filter1() );
Items.Add( new Filter1() );

Если у вас есть строка 'Filter1' в качестве переменной - реализуйте служебный метод 'instantiate' - внутри этой функции либоиметь оператор switch или использовать отражение:

Items.Add( instantiate( key ) );

private UserControl instantiate( string key ) {
    ...
}
...