locked
Binding error RRS feed

  • Question

  • I have a data model class with 2 public properties like this:
     
    Code Snippet
    public class Model : INotifyPropertyChanged
        {
            public ImageSequence ImageSequence
            {
                get {...}
                set {...}
            }
     
            public Gray12Image CurrentImage
            {
                get {...}
                set {...}
            }
        }

     

    where ImageSequence contains a single Gray12Image calles TopView and a list of Gray12Image (in a public property called Images). CurrentImage is the image that is currently worked on in the model.
    I made a user control called ImageSequenceView that shows the data bound ImageSequence with the TopView image in top and below that the images in the list in a list view. It has 2 dependency properties, the first is for the ImageSequence to display, the second is for the Gray12Image that is currently selected in the listview.
    It has the following code:
    XAML:
     

    <UserControl x:Class="DicomTool.ImageSequenceView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        >
     
      <UserControl.Resources>
        <DataTemplate x:Key="imageSequenceListViewItemTemplate"> 
     ... //the template for the image items in the ListView
        </DataTemplate>
      </UserControl.Resources>
     
      <StackPanel Orientation="Vertical">
        <Image x:Name="topView"
               VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="Uniform" Cursor="Cross"
                Source="{Binding ImageSequence.TopView}"/>
     
        <ListView SelectionMode="Single" ItemsSource="{Binding ImageSequence.Images}" ItemTemplate="{StaticResource imageSequenceListViewItemTemplate}" SelectedItem="{Binding SelectedImage}"/>
     
        <TextBlock Text="Test"/>
      </StackPanel>
    </UserControl>

     

    C#:
     
    Code Snippet
    namespace DicomTool
    {
        ///
        /// Interaction logic for ImageSequenceView.xaml
        ///
        public partial class ImageSequenceView : System.Windows.Controls.UserControl
        {
            public static readonly DependencyProperty ImageSequenceProperty = DependencyProperty.Register(
                "ImageSequence", typeof(ImageSequence), typeof(ImageSequenceView),
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsMeasure));
     
            public ImageSequence ImageSequence
            {
                get
                {
                    return (ImageSequence)GetValue(ImageSequenceProperty);
                }
                set
                {
                    SetValue(ImageSequenceProperty, value);
                }
            }
     
            public static readonly DependencyProperty SelectedImageProperty = DependencyProperty.Register(
                "SelectedImage", typeof(Gray12Image), typeof(ImageSequenceView),
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsMeasure));
     
            public Gray12Image SelectedImage
            {
                get
                {
                    return (Gray12Image)GetValue(SelectedImageProperty);
                }
                set
                {
                    if (!ImageSequence.Images.Contains(value))
                        throw new ArgumentException("SelectedImage");
     
                    SetValue(SelectedImageProperty, value);
                }
            }
     
            public ImageSequenceView()
            {
                InitializeComponent();
            }
        }
    }

     

     
    I embed this control in my main window1.xaml (the model instance is the DataContext of it) like this:
     
    Code Snippet
          <local:ImageSequenceView ImageSequence="{Binding Path=ImageSequence}" SelectedImage="{Binding Path=CurrentImage}" Width="200"/>

     

    I get the following errors when I start my program and when I change the ImageSequence from inside the model it has no effect on the contents of the UserControl:
     
    Code Snippet
    System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='System.Windows.Data.BindingExpression' BindingExpression:Path=ImageSequence; DataItem='ImageSequenceView' (Name=''); target element is 'ImageSequenceView' (Name=''); target property is 'ImageSequence' (type 'ImageSequence')
    System.Windows.Data Error: 35 : BindingExpression path error: 'CurrentImage' property not found on 'object' ''ImageSequenceView' (Name='')'. BindingExpression:Path=CurrentImage; DataItem='ImageSequenceView' (Name=''); target element is 'ImageSequenceView' (Name=''); target property is 'SelectedImage' (type 'Gray12Image')

     

     
    So what am I doing wrong?
    Thanks for your help.
    Monday, July 2, 2007 12:50 PM

Answers

  • Ok I found it: In the UserControl XAML definition I deleted the Data binding to itself and instead used a RelativeSource in the control property definitions themselves like this:
     
    Code Snippet
        <ListView SelectionMode="Single" ItemsSource="{Binding MyImageSequence.Images,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}}}" ItemTemplate="{StaticResource imageSequenceListViewItemTemplate}" SelectedItem="{Binding MySelectedImage,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}}}"/>

     

    Now it works, thanks for your poking! ;-)
    Tuesday, July 3, 2007 6:07 PM

All replies

  • Anyone an idea?
    Tuesday, July 3, 2007 7:06 AM
  • Basically I want to attach 2 properties of my model to 2 custom denpendency properties of my UserControl which are then internally forwarded (using XAML) to dependency properties of standard controls in the UserControl itself so that I don't have to care about the type and the sub properties of the 2 root properties in the main window1.xaml. Maybe I should do it another way?
    Tuesday, July 3, 2007 4:17 PM
  • It sounds like the problem is that the DataContext for the ImageSequenceView is the ImageSequenceView itself - I don't see anywhere in your sample that would cause a Model to be the DataContext?
    Tuesday, July 3, 2007 4:43 PM
  • Yes that is right, the UserControl (=ImageSequenceView) has itself as the DataContext because by doing that I can databind properties of the controls inside the UserControl to the custom dependency properties of the UserControl itself like this (code from the ImageSequenceView.xaml):
     
    Code Snippet
            <ListView SelectionMode="Single" ItemsSource="{Binding ImageSequence.Images}" ItemTemplate="{StaticResource imageSequenceListViewItemTemplate}" SelectedItem="{Binding SelectedImage}"/>

     

    ImageSequence (and its property Images) and SelectedImage are the c# wrappers of the custom dependency properties on the UserControl, that in turn should be set when I instantiate the UserControl in my main window1.xam using the model's (that is the DataContext of Window1) ImageSequence property and CurrentImage as the source of the data binding like this:
     
     
    Code Snippet
     <local:ImageSequenceView ImageSequence="{Binding Path=ImageSequence}" SelectedImage="{Binding Path=CurrentImage}" Width="200"/>

     

    Here ImageSequence and CurrentImage come from the model.
    I hope you can understand what I mean? ;-)
    Tuesday, July 3, 2007 5:19 PM
  • In the example you show, at least, the problematic binding appear within a UserControl which has set its DataContext to be itself.  While I too have used that self-referential binding technique, it does mean that the children will inherit this DataContext... (sorry if I'm still confused...)
    Tuesday, July 3, 2007 5:28 PM
  • No problem! ;-)
     
    I renamed all the properties so that I don't have anymore properties whose type is the same as their name.
    Now I get these errors:
     
    Code Snippet
    System.Windows.Data Error: 35 : BindingExpression path error: 'CurrentImageSequence' property not found on 'object' ''ImageSequenceView' (Name='')'. BindingExpression:Path=CurrentImageSequence; DataItem='ImageSequenceView' (Name=''); target element is 'ImageSequenceView' (Name=''); target property is 'MyImageSequence' (type 'ImageSequence')
    System.Windows.Data Error: 35 : BindingExpression path error: 'CurrentImage' property not found on 'object' ''ImageSequenceView' (Name='')'. BindingExpression:Path=CurrentImage; DataItem='ImageSequenceView' (Name=''); target element is 'ImageSequenceView' (Name=''); target property is 'MySelectedImage' (type 'Gray12Image')

     

    It really seems as if the data binding to itself in the ImageSequenceView destroys the original data source paths to the model properties (that are set here "   <local:ImageSequenceView MyImageSequence="{Binding Path=CurrentImageSequence}" MySelectedImage="{Binding Path=CurrentImage}" Width="200"/> // these are both from the model
    ") and the ImageSequenceView looks for these properties on itself instead of on the model as I intended. How could I achieve that?
    Thanks for your replies so far!
    Tuesday, July 3, 2007 5:49 PM
  • Ok I found it: In the UserControl XAML definition I deleted the Data binding to itself and instead used a RelativeSource in the control property definitions themselves like this:
     
    Code Snippet
        <ListView SelectionMode="Single" ItemsSource="{Binding MyImageSequence.Images,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}}}" ItemTemplate="{StaticResource imageSequenceListViewItemTemplate}" SelectedItem="{Binding MySelectedImage,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}}}"/>

     

    Now it works, thanks for your poking! ;-)
    Tuesday, July 3, 2007 6:07 PM