Привязка к свойствам зависимостей в ItemsControl

У меня есть ItemsControl со встроенным ItemsSource, как показано ниже (упрощенно):

<UserControl>
    <ItemsControl>         
            <ItemsControl.ItemsSource>
               <x:Array Type="y:KeyData">
                  <y:KeyData Name="Name1"/>
                  <y:KeyData Name="Name2"/>
               </x:Array>
            </ItemsControl.ItemsSource>
    </ItemsControl>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type DateDifferences:KeyData}">
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</UserControl>

Теперь я хочу привязать другое значение к каждому элементу KeyData. Я пробовал следующее:

<UserControl>
    <ItemsControl>         
            <ItemsControl.ItemsSource>
               <x:Array Type="y:KeyData">
                  <y:KeyData Name="Name1" Count="{Binding Count1}"/>
                  <y:KeyData Name="Name2" Count="{Binding Count2}"/>
               </x:Array>
            </ItemsControl.ItemsSource>
    </ItemsControl>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type DateDifferences:KeyData}">
            <TextBlock Text="{Binding Name}"/>
            <TextBlock Text="{Binding Count}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</UserControl>

И настройте свойство зависимости, как показано ниже:

   internal class KeyData : DependencyObject
    {
        public string Name { get; set; }

        public int? Count
        {
            get { return (int?)GetValue(CountProperty); }
            set { SetValue(CountProperty, value); }
        }

        public static readonly DependencyProperty CountProperty =
             DependencyProperty.Register("Count",
                                         typeof(int?),
                                         typeof(KeyData),
                                         new FrameworkPropertyMetadata());
    }

И перейдите в контекст данных:

<UserControlName DataContext="{Binding Container.APresenter}"/>

Однако привязки не могут найти источник...

Ошибка System.Windows.Data: 2: не удается найти управляющий элемент FrameworkElement или FrameworkContentElement для целевого элемента. BindingExpression:Путь=Удалено; Элемент данных = ноль; целевой элемент — «KeyData» (HashCode=4638229); целевое свойство — «Count» (тип «Nullable`1»)

Я думал, что это и есть смысл свойства зависимостей — обрабатывать такие случаи? Кто-нибудь может указать на часть, которую я неправильно понял?


person Chris    schedule 08.04.2015    source источник
comment
Какой объект, по вашему мнению, будет источником привязок Count1 и Count2? Вам нужно будет установить Source или RelativeSource или ElementName двух привязок, так как DataContext не наследуется в массиве.   -  person Clemens    schedule 08.04.2015
comment
Извините, как вы имеете в виду источник? Count1 будет int на APresenter.   -  person Chris    schedule 08.04.2015
comment
Да, но вы не поместили экземпляр APresenter ни в какой DataContext, только в DataContext времени разработки. Но даже если бы вы это сделали, DataContext не будет унаследован элементами массива.   -  person Clemens    schedule 08.04.2015
comment
@Clemens - я полагаю, что устанавливаю DataContext при создании элемента управления? Я обновлю свой вопрос. Итак, есть ли способ указать на него элементы массива?   -  person Chris    schedule 08.04.2015
comment
На ваш вопрос уже есть ответ...   -  person Clemens    schedule 08.04.2015
comment
@Clemens: Спасибо, я тоже пытаюсь работать над этим, к сожалению, попытка назвать мой UserControl, похоже, мешает компиляции всего ...   -  person Chris    schedule 08.04.2015
comment
Ах, не говоря уже о чате, я просто подумал, что это может очистить комментарии...   -  person Chris    schedule 09.04.2015


Ответы (2)


Привязка не знает, кому принадлежат Count1 и Count2. Укажите, возможно, ElementName, который относится к рассматриваемому объекту. Затем возможно отработайте его DataContext, например вот эту привязку:

="{Binding ElementName=PathBox, Path=DataContext.Count1}"

Я считаю, что именование элементов Xaml (даже страницы), а затем путь к этому именованному объекту в его внутренности или если он является элементом управления через его контекст данных, решает большинство проблем с привязкой.

Обновлять

Иногда нужно использовать x:reference для получить доступ к именованным элементам. В этом случае в зависимости от объекта используйте x: name, чтобы назвать его, а затем получить к нему доступ.

="{Binding Source={x:Reference PathBox} , Path=Count1}">
person ΩmegaMan    schedule 08.04.2015
comment
Спасибо, извините, пытался что-то вытащить из этого. Если я установил свой контекст данных, как в вопросе, доступен ли он только в элементе UserControl? Кажется, я не могу дать этому имя из-за этого (я думаю) - но в равной степени я не могу найти его и через RelativeSource... - person Chris; 08.04.2015
comment
Хм, нет, неважно, мой контекст данных должен быть установлен, так как я обращаюсь к нему для другого текстового блока. Но я, кажется, вообще не могу получить к нему доступ из элементов массива... - person Chris; 08.04.2015
comment
@Chris Если вы назвали UserControl, попробуйте просто Count1 вместо DataContext.Count1, поскольку в этом случае предполагается DataContext. - person ΩmegaMan; 08.04.2015
comment
Нет, похоже, это тоже не работает. Кажется, я не могу назвать свой UserControl (возможно, коллизия пространств имен?), но есть панель стека, обертывающая этот ItemsControl, который, как я вижу, имеет контекст данных из других привязок. Но я, кажется, не могу заполучить это изнутри Массива ни за любовь, ни за деньги... - person Chris; 08.04.2015
comment
@CHris, вы можете переместить свой массив данных из-под контроля в ресурс страницы? - person ΩmegaMan; 08.04.2015
comment
@Chris использует x:name для имени объекта. Иногда синтаксический анализатор Xaml не может обрабатывать атрибут «Имя» и требует x:name. - person ΩmegaMan; 08.04.2015
comment
Спасибо @OmegaMan - скоро я смогу вернуться к этому и попробовать это! (Я безуспешно пробовал x:Name назвать UserControl, но x:reference звучит многообещающе!) - person Chris; 08.04.2015
comment
Наконец удалось заставить все работать с помощью объекта Pipe, согласно второй половине этого вопроса. У меня были проблемы с x:Reference из-за циклических зависимостей, а затем были те же проблемы даже после извлечения массива в ресурсы. Это ужасно уродливый способ, но единственное, от чего мне удалось получить результат в конце ... Я опубликую полный ответ о том, что я сделал завтра. Спасибо за вашу помощь в этом, несмотря ни на что. - person Chris; 08.04.2015

Итак, окончательное решение.

Игнорируя очевидное, что я изначально пропустил контекст данных, после этого проблема, казалось, заключалась в том, чтобы сделать элементы в массиве осведомленными о контексте данных внешнего ItemsControl.

Я пытался ссылаться как на ElementName, так и на RelativeSource - оба найти было невозможно. Я попытался поместить x:Name в UserControl, а также сослаться на x:Reference, как предложил OmegaMan в своем ответе.

Ни один из них не имел желаемого эффекта - единственным рабочим решением, которое я смог найти, было использование "Pipe Object", как подробно описано во второй половине этого ответа.

С тех пор я преобразовал элементы массива в отдельный пользовательский элемент управления, что, в свою очередь, упростило привязки.

person Chris    schedule 10.04.2015