locked
How to Data Bind to complex properties (Shimon Sim) - 12/25/2007 4:51 AM PST RRS feed

  • Question

  • By: Shimon Sim


    I have ListBox which is bound to PersonCollection.
    Person class has property Address that has property Street.
    How can I bind TextBlock to Street?
    Thanks,
    Shimon.
    Friday, February 22, 2008 3:14 PM

All replies

  • By: Corrado Cavalli [MVP]


    <TextBlock Text="{Binding Path=Address.Street}" />


    --
    Corrado Cavalli [Microsoft .NET MVP-MCP]
    UGIdotNET -
    http://www.ugidotnet.org
    Weblog: http://blogs.ugidotnet.org/corrado/
    Monday, February 25, 2008 3:50 PM
  • By: Shimon Sim

    This doesn't work for me. Any idea why?
    Thanks
    "Corrado Cavalli [MVP]" <corradoNOSPAMPLEASE@mvps.org> wrote in message
    news:5tctt4F1d8k0jU2@mid.individual.net...
    > <TextBlock Text="{Binding Path=Address.Street}" />
    >
    >
    > --
    > Corrado Cavalli [Microsoft .NET MVP-MCP]
    > UGIdotNET -
    http://www.ugidotnet.org
    > Weblog: http://blogs.ugidotnet.org/corrado/
    >
    >

    Monday, February 25, 2008 3:50 PM
  • By: Corrado Cavalli [MVP]


    > This doesn't work for me. Any idea why?
    Please be more specific, what "doesn't work" means?
    Have you had a look at output window (hope you're also using Visual Studio
    2008) to see if some binding errors are listed?


    --
    Corrado Cavalli [Microsoft .NET MVP-MCP]
    UGIdotNET -
    http://www.ugidotnet.org
    Weblog: http://blogs.ugidotnet.org/corrado/
    Monday, February 25, 2008 3:51 PM
  • By: Shimon Sim


    Thanks. It did work. I didn't propagate Address's PropertyChanged Event to
    Person class so WPF didn't know to update.

    "Corrado Cavalli [MVP]" <corradoNOSPAMPLEASE@mvps.org> wrote in message
    news:5tctt4F1d8k0jU2@mid.individual.net...
    > <TextBlock Text="{Binding Path=Address.Street}" />
    >
    >
    > --
    > Corrado Cavalli [Microsoft .NET MVP-MCP]
    > UGIdotNET -
    http://www.ugidotnet.org
    > Weblog: http://blogs.ugidotnet.org/corrado/
    >
    >
    >
    Monday, February 25, 2008 3:52 PM
  • By: Steve White (MS)


    I'm not sure why you needed to do that. Here's a sample which doesn't do 
    that, yet Address.Street is updated.
    
    	<Window.Resources>
    		<ObjectDataProvider x:Key="PersonDS" d:IsDataSource="True" 
    ObjectType="{x:Type UntitledProject1:Person}"/>
    	</Window.Resources>
    
    	<Grid DataContext="{Binding Mode=OneWay, Source={StaticResource PersonDS}}">
    		<Label HorizontalAlignment="Left" Margin="180,149,0,0" 
    VerticalAlignment="Top" Content="{Binding Path=Name, Mode=Default}"/>
    		<Label HorizontalAlignment="Left" Margin="182,191,0,0" Content="{Binding 
    Path=Address.Street, Mode=Default}" d:LayoutOverrides="Height" 
    VerticalAlignment="Top"/>
    	</Grid>
    
        public class Address : INotifyPropertyChanged
        {
            string[] streets = { "s1", "s2", "s3", "s4" };
    
            public Address()
            {
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromSeconds(0.2);
                timer.Tick += delegate { this.Street = streets[(new 
    Random()).Next(streets.Length)]; };
                timer.Start();
            }
    
            public string Street
            {
                get { return _street; }
                set
                {
                    if (_street != value)
                    {
                        _street = value;
                        this.OnPropertyChanged("Street");
                    }
                }
            } string _street = "none";
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void OnPropertyChanged(string propertyName)
            {
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new 
    PropertyChangedEventArgs(propertyName));
                }
            }
        }
    
        public class Person : INotifyPropertyChanged
        {
            string[] names = { "n1", "n2", "n3", "n4" };
    
            public Person()
            {
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromSeconds(2);
                timer.Tick += delegate { this.Name = names[(new 
    Random()).Next(names.Length)]; };
                timer.Start();
            }
    
            public string Name
            {
                get { return _name; }
    			set
    			{
    				if (_name != value)
    				{
    					_name = value;
    					this.OnPropertyChanged("Name");
    				}
    			}
            } string _name = "none";
    
            public Address Address
            {
                get { return _address; }
                set
                {
                    if (_address != value)
                    {
                        _address = value;
                        this.OnPropertyChanged("Address");
                    }
                }
            } Address _address = new Address();
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void OnPropertyChanged(string propertyName)
            {
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new 
    PropertyChangedEventArgs(propertyName));
                }
            }
        }
    
    
    "Shimon Sim" wrote:
    
    > Thanks. It did work. I didn't propagate Address's PropertyChanged Event to 
    > Person class so WPF didn't know to update.
    > 
    > "Corrado Cavalli [MVP]" <corradoNOSPAMPLEASE@mvps.org> wrote in message 
    > news:5tctt4F1d8k0jU2@mid.individual.net...
    > > <TextBlock Text="{Binding Path=Address.Street}" />
    > >
    > >
    > > -- 
    > > Corrado Cavalli [Microsoft .NET MVP-MCP]
    > > UGIdotNET - http://www.ugidotnet.org
    > > Weblog: http://blogs.ugidotnet.org/corrado/
    > >
    > >
    > > 
    > 
    > 
    > 
    Monday, February 25, 2008 3:52 PM
  • By: Steve White (MS)


    I posted a reply to your most recent post, showing that you don't need to 
    propagate property change notifications up to the Person object if you bind 
    to Address.Street. An alternative is to use dependency properties if your 
    types can derive from DO:
    
        public class AddressDO : DependencyObject
        {
            string[] streets = { "s1_do", "s2_do", "s3_do", "s4_do" };
    
            public AddressDO()
            {
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromSeconds(0.2);
                timer.Tick += delegate { this.Street = streets[(new 
    Random()).Next(streets.Length)]; };
                timer.Start();
            }
    
            public static readonly DependencyProperty StreetProperty = 
    DependencyProperty.Register("Street", typeof(string), typeof(AddressDO), new 
    FrameworkPropertyMetadata("no street"));
    		public string Street
    		{
    			get { return (string)GetValue(StreetProperty); }
    			set { SetValue(StreetProperty, value); }
    		}
        }
    
        public class PersonDO : DependencyObject
        {
            string[] names = { "n1_do", "n2_do", "n3_do", "n4_do" };
    
            public PersonDO()
            {
                Address = new AddressDO();
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromSeconds(2);
                timer.Tick += delegate { this.Name = names[(new 
    Random()).Next(names.Length)]; };
                timer.Start();
            }
    
            public static readonly DependencyProperty NameProperty = 
    DependencyProperty.Register("Name", typeof(string), typeof(PersonDO), new 
    FrameworkPropertyMetadata("no name"));
            public string Name
            {
                get { return (string)GetValue(NameProperty); }
                set { SetValue(NameProperty, value); }
            }
    
            public static readonly DependencyProperty AddressProperty = 
    DependencyProperty.Register("Address", typeof(AddressDO), typeof(PersonDO));
            public AddressDO Address
            {
                get { return (AddressDO)GetValue(AddressProperty); }
                set { SetValue(AddressProperty, value); }
            }
        }
    
    
    "Shimon Sim" wrote:
    
    > I have ListBox which is bound to PersonCollection.
    > Person class has property Address that has property Street.
    > How can I bind TextBlock to Street?
    > Thanks,
    > Shimon. 
    > 
    > 
    > 
    Monday, February 25, 2008 3:53 PM