Инициализация ICollection в XAML - PullRequest
1 голос
/ 20 июня 2011

Попытка сделать что-то вроде этого ...

public class MiniObject
{
    public bool Checked { get; set; }
    public String Caption { get; set; }

    public ICollection<MiniObject> Content { get; set;}
}


<Window.Resources>
    <local:MiniObject x:Key="RootItem" Caption="Item0" Checked="True">
        <local:MiniObject.Content>
            <local:MiniObject Caption="Item1" Checked="True">
            </local:MiniObject>
            <local:MiniObject Caption="Item2" Checked="True">
            </local:MiniObject>
        </local:MiniObject.Content>
    </local:MiniObject>
</Window.Resources>

Это, конечно, не работает, возвращая ошибку:

Object of type 'WorkflowTest.MiniObject' cannot be converted to type 'System.Collections.Generic.ICollection`1[WorkflowTest.MiniObject]'.

Есть ли способ сделать это в WPF? Если да, мне нужно вообще изменить форму моих объектов или я могу просто предоставить специализированный объект, который использует только WPF, например ...

<Window.Resources>
    <local:MiniObject x:Key="RootItem" Caption="Item0" Checked="True">
        <local:MiniObject.Content>
            <local:MiniObjectCollection>
                <local:MiniObject Caption="Item1" Checked="True">
                </local:MiniObject>
                <local:MiniObject Caption="Item2" Checked="True">
                </local:MiniObject>
            </local:MiniObjectCollection>
        </local:MiniObject.Content>
    </local:MiniObject>
</Window.Resources>

Ответы [ 3 ]

1 голос
/ 20 июня 2011

Если только ваш код упоминается выше, он будет выдан как исключение нулевой ссылки для записи свойства коллекции в XAML из-за факта из MSDN :

The presence of that collection type is implicit whenever you specify a property 
in XAML that takes a collection type.

Итак, я предлагаю инициализировать коллекцию в XAML следующим образом, если вы не хотите иметь экземпляр коллекции в объявлении класса.

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System.Collections;assembly=mscorlib"  xmlns:local="clr-namespace:WpfApplication1"  Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:MiniObject x:Key="RootItem" Caption="Item0" Checked="True">
            <local:MiniObject.Content>
                <system:ArrayList>  -------------------------------------1)
                    <local:MiniObject Caption="Item1" Checked="True">
                    </local:MiniObject>
                    <local:MiniObject Caption="Item2" Checked="True">
                    </local:MiniObject>
                </system:ArrayList>
            </local:MiniObject.Content>
        </local:MiniObject>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding Source={StaticResource ResourceKey=RootItem}, Path=Content}" DisplayMemberPath="Caption"/>
    </Grid>
</Window>


public class MiniObject
{
    public bool Checked { get; set; }
    public String Caption { get; set; }

    public IList Content { get; set; } -----------------------------------------2)
}

В 2) вы можете знать, что есть четыре альтернативы (IList, IDictionary и т. Д.), Которые должны быть свойством коллекции в XAML. Пожалуйста, обратитесь к MSDN . Выше ICollection также в порядке, так как элементы добавляются в ArrayList.

В пункте 1) мы еще не можем объявить коллекцию универсальных типов, но я знаю, что она будет поддерживаться в ближайшее время.

1 голос
/ 20 июня 2011

Вы пытаетесь использовать неявный синтаксис коллекции XAML.Для этого свойство (в данном случае Content) должно иметь тип, реализующий ICollection.Примечание: не ICollection, а тип, который реализует ICollection.

. Вы не можете просто использовать интерфейс, потому что XamlReader должен знать, какой тип объекта создать.Если вы не указали тип, как он должен решить?Поиск во всех доступных для вашей сборки типах, поиск тех, которые реализуют ICollection<MiniObject>, отбрасывание тех, у которых нет конструктора без параметров, и затем случайный выбор одного из них?Нет.

Когда вы определяете Content как List<MiniObject>, XamlReader знает, какой тип объекта он должен создать.Поскольку этот тип реализует ICollection, он может использовать неявный синтаксис коллекции.Поэтому он просто создает объект и вызывает Add для добавления дочерних элементов, и если вы вставите туда дочерний элемент, который не является MiniObject, вы получите ошибку времени выполнения.

Вы говоритечто "мне нужно избегать использования фактической реализации" в вашем свойстве Content.В этом случае вы не можете использовать неявный синтаксис коллекции.Вам нужно будет сделать то, что вы делаете во втором примере: явно определить тип, который реализует ICollection<MiniObject>, и добавить дочерний элемент в ваш XAML, чтобы создать его явно.

0 голосов
/ 20 сентября 2017

У меня тоже такое же требование, и я реализовал его так же, как вы делаете @NtscCobalt, и получил то же исключение,

. Одним простым решением этого исключения является инициализация свойства Content с некоторой коллекцией List <> илиOvservableCollection <>.

Это сработало для меня.Также, если вы используете IEnumerable вместо IList, это приведет к ошибкам сборки.

private IList<MiniObject> _content = new List<MiniObject>();
public IList<MiniObject> Content 
{ 
    get
    {
        return _content;
    } 
    set
    {
        _content=value;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...