Свързване към свойства на зависимост в 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:Path=Премахнато; DataItem=null; целевият елемент е „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 предложи в отговора си.

Нито едно от тях нямаше желания ефект - единственото работещо решение, което можах да намеря, беше да използвам "Тръбен обект", както е описано подробно във втората половина на този отговор.

Оттогава преработих елементите на масива в отделен потребителски контрол, което от своя страна опрости свързванията.

person Chris    schedule 10.04.2015