1

I have an ItemsControl with an inline ItemsSource as below (simplified):

<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>

I now want to bind another value to each KeyData item. I've tried the below:

<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>

And set up a dependency property as below:

   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());
    }

And pass in a Data Context:

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

However, the bindings are failing to locate the source...

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Removed; DataItem=null; target element is 'KeyData' (HashCode=4638229); target property is 'Count' (type 'Nullable`1')

I thought this was the point of a Dependency Property - to handle cases like this? Is anyone able to point out the part I've misunderstood?

Chris
  • 5,882
  • 2
  • 32
  • 57
  • Which object do you expect to be the source of the `Count1` and `Count2` bindings? You would have to set the Source or RelativeSource or ElementName of the two bindings, as no DataContext is inherited into the Array. – Clemens Apr 08 '15 at 16:11
  • Sorry, how do you mean the source? Count1 would be an int on APresenter. – Chris Apr 08 '15 at 16:14
  • Yes, but you haven't put an APresenter instance into any DataContext, only into a design time DataContext. But even if you had done that, the DataContext won't be inherited be the elements in the Array. – Clemens Apr 08 '15 at 16:17
  • @Clemens - I believe I'm setting the DataContext when creating the control? I'll update my question. So is there a way I can point the elements in the array to it? – Chris Apr 08 '15 at 16:27
  • There is already an answer to your question... – Clemens Apr 08 '15 at 16:30
  • @Clemens: Thank you, I'm attempting to work on that one also, unfortunately, trying to name my UserControl seems to be preventing everything from compiling... – Chris Apr 08 '15 at 16:36
  • Ah, never mind chat, I just thought it might clear the comments... – Chris Apr 09 '15 at 08:58

2 Answers2

1

The binding does not know who owns Count1 and Count2. Provide maybe an ElementName which refers to the object in question. Then possibly work off of its DataContext such as this binding:

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

I find that naming Xaml elements (even the page) then pathing to that named object into its internals or if it is a control via its datacontext solves most binding issues.

Update

Sometimes one has to x:reference to access named items. In that case depending on the object use x:name to name it then access it.

="{Binding Source={x:Reference PathBox} , Path=Count1}">
ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
  • Thanks, sorry, been trying to get something out of this. If I've set my datacontext as in the question, is it only accessible on the UserControl element? I don't seem to be able to give that a name, because of [this](http://stackoverflow.com/questions/14496353/cant-set-xname-root-on-usercontrol) (I think) - but equally, I don't seem to be able to locate it through RelativeSource either... – Chris Apr 08 '15 at 16:52
  • Hmm, no, nevermind, my data context must be set, as I'm accessing it for another textblock. But I don't seem to be able to access it from the Array items at all... – Chris Apr 08 '15 at 16:56
  • @Chris If you have named the UserControl, try just `Count1` instead of `DataContext.Count1` for in that case the DataContext is assumed. – ΩmegaMan Apr 08 '15 at 16:59
  • No, that doesn't seem to be doing it either. I don't seem to be able to name my UserControl (namespace collision, perhaps?), but there's a stackpanel wrapping this ItemsControl, which I can see does have the data context from other bindings. But I don't seem to be able to get hold of that from within the Array for love nor money... – Chris Apr 08 '15 at 17:04
  • @CHris can you move your data array out of the control to the page's resource? – ΩmegaMan Apr 08 '15 at 17:51
  • @Chris use `x:name` to name the object. Sometimes the Xaml Parser can't handle the 'Name' attribute and needs `x:name`. – ΩmegaMan Apr 08 '15 at 18:13
  • Thanks @OmegaMan - I'll be able to get back to this soon and try these out! (I've tried x:Name to name the UserControl without success, but x:reference sounds promising!) – Chris Apr 08 '15 at 18:52
  • Finally managed to get things working through using a Pipe object, as per the second half of [this question](http://stackoverflow.com/a/8247368/1768779). I had issues with x:Reference due to cyclic dependencies, and then had the same issues even after extracting the array to resources. It's a horrible ugly way, but the only thing I could manage to get a result from in the end...I'll post a full answer of what I did tomorrow. Thanks for your help on this one, regardless. – Chris Apr 08 '15 at 20:20
0

So, the eventual resolution.

Ignoring the obvious, that I'd missed a data context originally, after that, the challenge seemed to be in making the items in the array aware of the data context of the outside ItemsControl.

I tried referencing by both ElementName and RelativeSource - both of which it didn't seem possible to find. I tried to put an x:Name on the UserControl, and also reference using x:Reference as OmegaMan suggested in his answer.

None of these had the desired effect - the only working solution I could find was to use a "Pipe Object", as detailed in the second half of this answer.

I have since refactored the array items into a separate user control, which in turn simplified the bindings.

Community
  • 1
  • 1
Chris
  • 5,882
  • 2
  • 32
  • 57