views:

495

answers:

2

Can somone give example of Dependency Property in ViewModel in WPF passed as datacontext to view. Will this require inheriting from DependencyObject? Lets say I want ListBox SelectedItem bound to a Dependency Property CurrentItem in ViewModel. I have it working from window object but same thing donnt work with ViewModel . In ViewModel I use GetProperty and SetProperty and not CLR property.

public partial class Window1 : Window
    {

        ObservableCollection<Person> persons;


        public ObservableCollection<Person> Persons
        {
            get
            {
                return persons;
            }

            set
            {
                persons = value;
            }
        }


        public static readonly DependencyProperty InfoTextProperty =
   DependencyProperty.Register(
      "InfoText",
      typeof(Person),
      typeof(Window1),
      new FrameworkPropertyMetadata(
         new PropertyChangedCallback(ChangeText)));

        public Window1()
        {
            InitializeComponent();
            this.DataContext = this;
            List<Person> people = new List<Person>();
            people.Add(new Person("Makeda Wilde"));
            people.Add(new Person(" Rosamaria Becnel"));
            people.Add(new Person("Jarrett Bernstein"));
            people.Add(new Person(" Leopoldo Palmer"));
            people.Add(new Person("Tyron Fisher"));
            people.Add(new Person(" Elba Kilpatrick"));
            people.Add(new Person("Ivory Lavender"));
            persons = new ObservableCollection<Person>(people);

            //persons.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(persons_CollectionChanged);
        }

        void persons_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {

        }


        public ListBoxItem InfoText
        {
            get
            {
                return (ListBoxItem)GetValue(InfoTextProperty);
            }
            set
            {
                SetValue(InfoTextProperty, value);
            }
        }


        private static void ChangeText(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            Person newPerson = (Person)e.NewValue;
            newPerson.IsSelected = true;

            Person oldPerson = (Person)e.OldValue;
            if (oldPerson != null)
            {
                oldPerson.IsSelected = false;
            }
        }







        //  #region INotifyPropertyChanged Members

        //  event PropertyChangedEventHandler PropertyChanged;
        //   // Create the OnPropertyChanged method to raise the event
        //protected void OnPropertyChanged(string name)
        //{
        //    PropertyChangedEventHandler handler = PropertyChanged;
        //    if (handler != null)
        //    {
        //        handler(this, new PropertyChangedEventArgs(name));
        //    }
        //}


        //  #endregion
    }


    public class Person : INotifyPropertyChanged
    {
        private bool isselected = false;
        public Person(string name)
        {
            this.Name = name;
            this.IsSelected = false;

        }
        public string Name { get; set; }
        public bool IsSelected
        {
            get
            {
                return isselected;
            }
            set
            {

                isselected = value;
                OnPropertyChanged("IsSelected");
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        // Create the OnPropertyChanged method to raise the event

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion


    }



<Grid>
        <ListBox Height="500"  Width="500" ItemsSource="{Binding Persons}"  Margin="104,46,212,0"  VerticalAlignment="Top"  SelectedItem="{Binding InfoText}"  >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Margin="2,2,2,2"  x:Name="tb" TextWrapping="Wrap" Text="{Binding Path=Name}"  />
                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding Path=IsSelected}" Value="true">
                            <Setter Property="Background"  TargetName="tb" Value="Red"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
A: 

In order to define a DependencyProperty in your view model, your view model class must derive from DependencyObject. Otherwise the DependencyProperty won't work right.

Do you really need the property to be a DependencyPropety? Have you looked into implementing INotifyPropertyChanged instead?

Andy
@andy- This is a learning project. I am looking at why this is not possible. I tried with INotifyPropertyChanged and it does work but what if I get Business Objects on which I do not have control? I am not looking for clearcut answers any advise is welcome.
TheMar
If you don't have control over your Business Objects, that the role of the ViewModel class to wrap it into something designed for being used with WPF possibilities (databinding, command...)
Jalfp
I have collection of Person called children as property of Person class. Assume they dont implement InotifyPropertyChanged. I can have ListBox bound to observableCollection<Person> property of view model. A Child ListBox will be bound to Children collection. If you make any changes to children collection it will not be reflected back to WPF ( as No INotifyPropertyChanged). Am I wrong in this assumption? If not I was hoping I will be able to solve this using Dependency Property --like to send IsSelected for children. Is there any other wrapping that can be done in ViewModel for children colect.
TheMar
A: 

Although you can implement a ViewModel as a DependencyObject with dependency properties, most people agree that it's better to use a POCO object implementing INotifyPropertyChanged... Have a look at this article by Kent Boogaart for a detailed comparison between the two approaches. There's also a SO question about this

Thomas Levesque