Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. WPF
  4. Another DependencyProperty Question

Another DependencyProperty Question

Scheduled Pinned Locked Moved WPF
wpfdata-structurestutorialquestioncareer
21 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    Kevin Marois
    wrote on last edited by
    #1

    I am still struggling to understand how to use DP's.... I am designing a Job Picker control[^]. The control is housed inside a Select Job window and also inside a wizard. When the user clicks a Job, I want that job exposed as a DP so the Window or Wizard know that a job was selected. In the Window, when a Job is selected, the Select button will come on. So in the control there is the tree:

    It's bound to Jobs and has it's SelectedItem bound to SelectedJob: The JobListControl's VM is JobListViewModel:

    #region Bound Properties
    private ObservableCollection _Jobs;
    public ObservableCollection Jobs
    {
    get { return _Jobs; }
    set
    {
    if (_Jobs == value)
    return;

        \_Jobs = value;
        RaisePropertyChanged("Jobs");
    }
    

    }

    private JobSummaryModel _SelectedJob;
    public JobSummaryModel SelectedJob
    {
    get { return _SelectedJob; }
    set
    {
    if (_SelectedJob == value)
    return;

        \_SelectedJob = value;
        RaisePropertyChanged("SelectedJob");
    }
    

    }
    #endregion

    This all works fine. When I click a Job in the tree, the SelectedJob property fires. So far so good. Now, I need to expose the SelectedJob to the control's host (either the SelectJob window or the Wizard). So I went into the code behind and added a DP:

    public partial class JobListView : UserControl
    {
        public JobListView()
        {
            InitializeComponent();
        }
    
        #region SelectedJob DP
        public JobSummaryModel SelectedJob
        {
            get { return (JobSummaryModel)GetValue(SelectedJobProperty); }
            set { SetValue(SelectedJobProperty, value); }
        }
    
        public static readonly DependencyProperty SelectedJobProperty = DependencyProperty.Register("SelectedJob", typeof(JobSummaryModel),
              typeof(JobListView));
        #endregion
    }
    

    Next, in the Window's XAML I have:

    P Richard DeemingR 2 Replies Last reply
    0
    • K Kevin Marois

      I am still struggling to understand how to use DP's.... I am designing a Job Picker control[^]. The control is housed inside a Select Job window and also inside a wizard. When the user clicks a Job, I want that job exposed as a DP so the Window or Wizard know that a job was selected. In the Window, when a Job is selected, the Select button will come on. So in the control there is the tree:

      It's bound to Jobs and has it's SelectedItem bound to SelectedJob: The JobListControl's VM is JobListViewModel:

      #region Bound Properties
      private ObservableCollection _Jobs;
      public ObservableCollection Jobs
      {
      get { return _Jobs; }
      set
      {
      if (_Jobs == value)
      return;

          \_Jobs = value;
          RaisePropertyChanged("Jobs");
      }
      

      }

      private JobSummaryModel _SelectedJob;
      public JobSummaryModel SelectedJob
      {
      get { return _SelectedJob; }
      set
      {
      if (_SelectedJob == value)
      return;

          \_SelectedJob = value;
          RaisePropertyChanged("SelectedJob");
      }
      

      }
      #endregion

      This all works fine. When I click a Job in the tree, the SelectedJob property fires. So far so good. Now, I need to expose the SelectedJob to the control's host (either the SelectJob window or the Wizard). So I went into the code behind and added a DP:

      public partial class JobListView : UserControl
      {
          public JobListView()
          {
              InitializeComponent();
          }
      
          #region SelectedJob DP
          public JobSummaryModel SelectedJob
          {
              get { return (JobSummaryModel)GetValue(SelectedJobProperty); }
              set { SetValue(SelectedJobProperty, value); }
          }
      
          public static readonly DependencyProperty SelectedJobProperty = DependencyProperty.Register("SelectedJob", typeof(JobSummaryModel),
                typeof(JobListView));
          #endregion
      }
      

      Next, in the Window's XAML I have:

      P Offline
      P Offline
      Pete OHanlon
      wrote on last edited by
      #2

      First of all your property should be static, like this;

      public static JobSummaryModel SelectedJob

      Chill _Maxxx_
      CodeStash - Online Snippet Management | My blog | MoXAML PowerToys | Mole 2010 - debugging made easier

      K 1 Reply Last reply
      0
      • P Pete OHanlon

        First of all your property should be static, like this;

        public static JobSummaryModel SelectedJob

        Chill _Maxxx_
        CodeStash - Online Snippet Management | My blog | MoXAML PowerToys | Mole 2010 - debugging made easier

        K Offline
        K Offline
        Kevin Marois
        wrote on last edited by
        #3

        I tried it, but it won't compile. I get

        An object reference is required for the non-static field, method, or property 'System.Windows.DependencyObject.SetValue(System.Windows.DependencyProperty, object)'

        Same on the getter.

        If it's not broken, fix it until it is

        S P 2 Replies Last reply
        0
        • K Kevin Marois

          I am still struggling to understand how to use DP's.... I am designing a Job Picker control[^]. The control is housed inside a Select Job window and also inside a wizard. When the user clicks a Job, I want that job exposed as a DP so the Window or Wizard know that a job was selected. In the Window, when a Job is selected, the Select button will come on. So in the control there is the tree:

          It's bound to Jobs and has it's SelectedItem bound to SelectedJob: The JobListControl's VM is JobListViewModel:

          #region Bound Properties
          private ObservableCollection _Jobs;
          public ObservableCollection Jobs
          {
          get { return _Jobs; }
          set
          {
          if (_Jobs == value)
          return;

              \_Jobs = value;
              RaisePropertyChanged("Jobs");
          }
          

          }

          private JobSummaryModel _SelectedJob;
          public JobSummaryModel SelectedJob
          {
          get { return _SelectedJob; }
          set
          {
          if (_SelectedJob == value)
          return;

              \_SelectedJob = value;
              RaisePropertyChanged("SelectedJob");
          }
          

          }
          #endregion

          This all works fine. When I click a Job in the tree, the SelectedJob property fires. So far so good. Now, I need to expose the SelectedJob to the control's host (either the SelectJob window or the Wizard). So I went into the code behind and added a DP:

          public partial class JobListView : UserControl
          {
              public JobListView()
              {
                  InitializeComponent();
              }
          
              #region SelectedJob DP
              public JobSummaryModel SelectedJob
              {
                  get { return (JobSummaryModel)GetValue(SelectedJobProperty); }
                  set { SetValue(SelectedJobProperty, value); }
              }
          
              public static readonly DependencyProperty SelectedJobProperty = DependencyProperty.Register("SelectedJob", typeof(JobSummaryModel),
                    typeof(JobListView));
              #endregion
          }
          

          Next, in the Window's XAML I have:

          Richard DeemingR Offline
          Richard DeemingR Offline
          Richard Deeming
          wrote on last edited by
          #4

          I might be missing something, but from what I can see:

          • The TreeViewEx's SelectedItem is bound to the SelectedJob property on the JobListViewModel;
          • The JobListView's SelectedJob is bound to the SelectJobWindowViewModel's SelectedJob property;
          • The JobListViewModel's SelectedJob is not connected in any way to the JobListView's SelectedJob;

          I think you need to connect the two SelectedJob properties. Something like this should work:

          public JobListView()
          {
          InitializeComponent();

          var binding = new Binding("DataContext.SelectedJob") { Source = this };
          SetBinding(SelectedJobProperty, binding);
          

          }


          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

          "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

          S 1 Reply Last reply
          0
          • K Kevin Marois

            I tried it, but it won't compile. I get

            An object reference is required for the non-static field, method, or property 'System.Windows.DependencyObject.SetValue(System.Windows.DependencyProperty, object)'

            Same on the getter.

            If it's not broken, fix it until it is

            S Offline
            S Offline
            SledgeHammer01
            wrote on last edited by
            #5

            Pete must have been smoking some really good dope when he answered you :). Your code is correct how you have it. I'm assuming you got rid of the: private JobSummaryModel _SelectedJob; public JobSummaryModel SelectedJob { get { return _SelectedJob; } set { if (_SelectedJob == value) return; _SelectedJob = value; RaisePropertyChanged("SelectedJob"); } } stuff and REPLACED it with: public JobSummaryModel SelectedJob { get { return (JobSummaryModel)GetValue(SelectedJobProperty); } set { SetValue(SelectedJobProperty, value); } } public static readonly DependencyProperty SelectedJobProperty = DependencyProperty.Register("SelectedJob", typeof(JobSummaryModel), typeof(JobListView)); ?? The key point here that everybody seems to be forgetting is that DPs don't go through the C# getter / setter (when binding). That is only there to make it easier to get/set the DP from the code. Your SelectedJob method is *COMPLETELY* bypassed by the binding system. Use one of the DependencyProperty.Register overloads that take a property changed callback. That is the ONLY way you can determine when a DP value changes.

            J K 2 Replies Last reply
            0
            • Richard DeemingR Richard Deeming

              I might be missing something, but from what I can see:

              • The TreeViewEx's SelectedItem is bound to the SelectedJob property on the JobListViewModel;
              • The JobListView's SelectedJob is bound to the SelectJobWindowViewModel's SelectedJob property;
              • The JobListViewModel's SelectedJob is not connected in any way to the JobListView's SelectedJob;

              I think you need to connect the two SelectedJob properties. Something like this should work:

              public JobListView()
              {
              InitializeComponent();

              var binding = new Binding("DataContext.SelectedJob") { Source = this };
              SetBinding(SelectedJobProperty, binding);
              

              }


              "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

              S Offline
              S Offline
              SledgeHammer01
              wrote on last edited by
              #6

              Please don't set data bindings via code :). You get a slap on the wrist for that.

              1 Reply Last reply
              0
              • S SledgeHammer01

                Pete must have been smoking some really good dope when he answered you :). Your code is correct how you have it. I'm assuming you got rid of the: private JobSummaryModel _SelectedJob; public JobSummaryModel SelectedJob { get { return _SelectedJob; } set { if (_SelectedJob == value) return; _SelectedJob = value; RaisePropertyChanged("SelectedJob"); } } stuff and REPLACED it with: public JobSummaryModel SelectedJob { get { return (JobSummaryModel)GetValue(SelectedJobProperty); } set { SetValue(SelectedJobProperty, value); } } public static readonly DependencyProperty SelectedJobProperty = DependencyProperty.Register("SelectedJob", typeof(JobSummaryModel), typeof(JobListView)); ?? The key point here that everybody seems to be forgetting is that DPs don't go through the C# getter / setter (when binding). That is only there to make it easier to get/set the DP from the code. Your SelectedJob method is *COMPLETELY* bypassed by the binding system. Use one of the DependencyProperty.Register overloads that take a property changed callback. That is the ONLY way you can determine when a DP value changes.

                J Offline
                J Offline
                Jason Gleim
                wrote on last edited by
                #7

                I thought I read in the OP's first message that he put the DP code in the code behind for the page. We should point out that the DP code and the property should both be defined in the view model. Nothing should be in the code behind!

                K 1 Reply Last reply
                0
                • K Kevin Marois

                  I tried it, but it won't compile. I get

                  An object reference is required for the non-static field, method, or property 'System.Windows.DependencyObject.SetValue(System.Windows.DependencyProperty, object)'

                  Same on the getter.

                  If it's not broken, fix it until it is

                  P Offline
                  P Offline
                  Pete OHanlon
                  wrote on last edited by
                  #8

                  Slap my head sideways. This is what happens when I post after 3 hours sleep. With a DP, you provide a static Set... And Get... For the static reference.

                  Chill _Maxxx_
                  CodeStash - Online Snippet Management | My blog | MoXAML PowerToys | Mole 2010 - debugging made easier

                  1 Reply Last reply
                  0
                  • J Jason Gleim

                    I thought I read in the OP's first message that he put the DP code in the code behind for the page. We should point out that the DP code and the property should both be defined in the view model. Nothing should be in the code behind!

                    K Offline
                    K Offline
                    Kevin Marois
                    wrote on last edited by
                    #9

                    First, I don't agree with the "Nothing in the code behind" mantra. Second, if the DP is in the VM, then how does the control's host see it? It won't.

                    If it's not broken, fix it until it is

                    J S 2 Replies Last reply
                    0
                    • K Kevin Marois

                      First, I don't agree with the "Nothing in the code behind" mantra. Second, if the DP is in the VM, then how does the control's host see it? It won't.

                      If it's not broken, fix it until it is

                      J Offline
                      J Offline
                      Jason Gleim
                      wrote on last edited by
                      #10

                      Whether you agree with it or not, it doesn't change the fact that is the accepted method of implementing MVVM. They aren't called best practices because somebody arbitrarily thinks there shouldn't be code in the code-behind. There are very few instances where code in the code behind is the only option. And putting the DP implementation in the code behind is not one of those times. Secondly, do you actually know how the DP system works and how the property binding system works? Do you even know why you use dependency properties? Your comments make me think not. The DP system is pubic and static... it is accessible from anywhere in your code. The binding framework knows how to find the DP if the underlying property has been registered with it. Normal developers put the DP code in the view model so it only gets instantiated once. But you probably don't agree with that mantra either. You seem sure that the control can't see the DP unless it is in the code behind but the dozens of programs I've written in Silverlight, WPF, WinRT, and Windows Phone all seem to work perfectly fine without a single DP in a code behind. And for the life of me, I can't find any real examples of someone suggesting that it goes in the code behind. Clearly I must be doing something wrong...

                      K 1 Reply Last reply
                      0
                      • J Jason Gleim

                        Whether you agree with it or not, it doesn't change the fact that is the accepted method of implementing MVVM. They aren't called best practices because somebody arbitrarily thinks there shouldn't be code in the code-behind. There are very few instances where code in the code behind is the only option. And putting the DP implementation in the code behind is not one of those times. Secondly, do you actually know how the DP system works and how the property binding system works? Do you even know why you use dependency properties? Your comments make me think not. The DP system is pubic and static... it is accessible from anywhere in your code. The binding framework knows how to find the DP if the underlying property has been registered with it. Normal developers put the DP code in the view model so it only gets instantiated once. But you probably don't agree with that mantra either. You seem sure that the control can't see the DP unless it is in the code behind but the dozens of programs I've written in Silverlight, WPF, WinRT, and Windows Phone all seem to work perfectly fine without a single DP in a code behind. And for the life of me, I can't find any real examples of someone suggesting that it goes in the code behind. Clearly I must be doing something wrong...

                        K Offline
                        K Offline
                        Kevin Marois
                        wrote on last edited by
                        #11
                        1. I started my original post with "I'm still struggling to understand DP's", so, no, I don't understand DP's, hence my post. 2) Your comments on the 'accepted method of implementing MVVM' are subjective. Just because I don't fully understand DP's doesn't mean I also don't understand WPF/MVVM. I've been doing MVVM for a long time with no problems. I just haven't used DP's and I thought I needed one here. MVVM simply calls for a separation of concerns. So what concerns are we talking about? Data vs UI. There's no law that states you can't put code in the code behind. The MVVM principle would not be violated if the code in the code behind was UI related. Do some Googling on "MVVM Code IN Code Behind" and you'll see lot's of discussions on folks putting UI code in the code behind to make their UI more functional. Having said all that, I personally try to avoid code in the code behind simply because I don't see a need for it, and also because I don't want code in 2 places. But that doesn't make me a purist in any sense. 3) I'm not sure what you mean by "Normal developers put the DP code in the view model so it only gets instantiated once. But you probably don't agree with that mantra either." a) I am a 'Normal developer' (I'm confused by this comment) b) If the DP was in the View or VM - what would make it instantiate more than once?? My view's code behind and my VM's only ever instantiate once each. Again, confusing statement I'm totally open to putting the DP in the VM. But when I've done that in the past it doesn't show up in the XAML. My JobListView control has the DP in the code behind. Therefore it's compiled into the same component. You of course know that the XAML and Code Behind are one, so putting the DP in the code behind allows it to be visible in the XAML of the view hosting the user control:

                        In this case, 'SelectedJob' is the DP defined in the JobListView code behind. Move the DP to the VM and this XAML is broken. Again, all this is based on my limited knowledge of DB's. I have yet to see a decent tutorial on how to USE them. Not DEFINE them - USE them. There's a difference. Thanks

                        If it's not broken, fix it until it is

                        J 1 Reply Last reply
                        0
                        • S SledgeHammer01

                          Pete must have been smoking some really good dope when he answered you :). Your code is correct how you have it. I'm assuming you got rid of the: private JobSummaryModel _SelectedJob; public JobSummaryModel SelectedJob { get { return _SelectedJob; } set { if (_SelectedJob == value) return; _SelectedJob = value; RaisePropertyChanged("SelectedJob"); } } stuff and REPLACED it with: public JobSummaryModel SelectedJob { get { return (JobSummaryModel)GetValue(SelectedJobProperty); } set { SetValue(SelectedJobProperty, value); } } public static readonly DependencyProperty SelectedJobProperty = DependencyProperty.Register("SelectedJob", typeof(JobSummaryModel), typeof(JobListView)); ?? The key point here that everybody seems to be forgetting is that DPs don't go through the C# getter / setter (when binding). That is only there to make it easier to get/set the DP from the code. Your SelectedJob method is *COMPLETELY* bypassed by the binding system. Use one of the DependencyProperty.Register overloads that take a property changed callback. That is the ONLY way you can determine when a DP value changes.

                          K Offline
                          K Offline
                          Kevin Marois
                          wrote on last edited by
                          #12

                          Why remove the SelectedJob property? The tree in JobListView has it's selecteditem bound to it. How would the VM know a job was selected?? This is hard to discuss without posting tons of code.

                          If it's not broken, fix it until it is

                          1 Reply Last reply
                          0
                          • K Kevin Marois
                            1. I started my original post with "I'm still struggling to understand DP's", so, no, I don't understand DP's, hence my post. 2) Your comments on the 'accepted method of implementing MVVM' are subjective. Just because I don't fully understand DP's doesn't mean I also don't understand WPF/MVVM. I've been doing MVVM for a long time with no problems. I just haven't used DP's and I thought I needed one here. MVVM simply calls for a separation of concerns. So what concerns are we talking about? Data vs UI. There's no law that states you can't put code in the code behind. The MVVM principle would not be violated if the code in the code behind was UI related. Do some Googling on "MVVM Code IN Code Behind" and you'll see lot's of discussions on folks putting UI code in the code behind to make their UI more functional. Having said all that, I personally try to avoid code in the code behind simply because I don't see a need for it, and also because I don't want code in 2 places. But that doesn't make me a purist in any sense. 3) I'm not sure what you mean by "Normal developers put the DP code in the view model so it only gets instantiated once. But you probably don't agree with that mantra either." a) I am a 'Normal developer' (I'm confused by this comment) b) If the DP was in the View or VM - what would make it instantiate more than once?? My view's code behind and my VM's only ever instantiate once each. Again, confusing statement I'm totally open to putting the DP in the VM. But when I've done that in the past it doesn't show up in the XAML. My JobListView control has the DP in the code behind. Therefore it's compiled into the same component. You of course know that the XAML and Code Behind are one, so putting the DP in the code behind allows it to be visible in the XAML of the view hosting the user control:

                            In this case, 'SelectedJob' is the DP defined in the JobListView code behind. Move the DP to the VM and this XAML is broken. Again, all this is based on my limited knowledge of DB's. I have yet to see a decent tutorial on how to USE them. Not DEFINE them - USE them. There's a difference. Thanks

                            If it's not broken, fix it until it is

                            J Offline
                            J Offline
                            Jason Gleim
                            wrote on last edited by
                            #13

                            I see I was getting a bit snarky in the previous reply. Sorry about that... I shouldn't do that. Please accept my apologizes. Now, onto your questions... MVVM is about separation of concerns but it is the WHY that really drives the structure. The idea is that if you remove "backward" dependencies, then you can swap layers in and out or reuse them. So the view depends on the view model but you can't have anything in the view model depend on the view. Similarly, the view model depends on the model (if implemented) but the model can't depend on the view model at all. If implemented this way, you can reuse the code at the VM and M levels. A single model could support multiple VM's. A single VM could support multiple views. Imagine, for a second, that you had an app that the main view displayed a list of customers. Supposed that your default view was a grid listing of those customers. What if you wanted to show them as tiles that could be rearranged? That would probably be best done in a different view. While you would only have one active view at any time, both views would bind to the same view model where you would maintain the data and the state. For example the "selected" customer shouldn't change if the user simply changes views. If you put anything that is outside of the scope of a single view in the code behind, then you have issues of scope and possible coupling between your view(s) and your view model(s). That is the reason to avoid putting code in the code behind. It is easy to say that it is no big deal when you have a 1 to 1 to 1 mapping. But it becomes a big deal when that changes. So the best practice is to avoid it so you don't have to go back and refactor if something changes. And... that really answers the questions about dependency properties. DP's are used by the binding system to hook-up properties between two classes for automatic synchronization. If you are going to bind two properties (which is what you are doing with the selected row on the treeview and the corresponding property on the view model) then ONE of them has to be a dependency property. So a DP hooked to a DP will work. A DP hooked to a regular property will work. But a regular property hooked to a regular property will not work. The binding framework in this case, can't resolve the property name raised in the propertychanged event because the framework uses the dependency property system to resolve the property names and update the values. The DP system is a static class so there is one instance of it for your appl

                            K 1 Reply Last reply
                            0
                            • K Kevin Marois

                              First, I don't agree with the "Nothing in the code behind" mantra. Second, if the DP is in the VM, then how does the control's host see it? It won't.

                              If it's not broken, fix it until it is

                              S Offline
                              S Offline
                              SledgeHammer01
                              wrote on last edited by
                              #14

                              First, I agree with Jason. If you need code in the code behind "you're doing it wrong". Second, why wouldn't EVERYBODY see the DP? It's a public static property. You would reference it like you would any other static property. EDIT: The DP doesn't belong in the VM anymore then it belongs in the CodeBehind. It belongs in the control class.

                              1 Reply Last reply
                              0
                              • J Jason Gleim

                                I see I was getting a bit snarky in the previous reply. Sorry about that... I shouldn't do that. Please accept my apologizes. Now, onto your questions... MVVM is about separation of concerns but it is the WHY that really drives the structure. The idea is that if you remove "backward" dependencies, then you can swap layers in and out or reuse them. So the view depends on the view model but you can't have anything in the view model depend on the view. Similarly, the view model depends on the model (if implemented) but the model can't depend on the view model at all. If implemented this way, you can reuse the code at the VM and M levels. A single model could support multiple VM's. A single VM could support multiple views. Imagine, for a second, that you had an app that the main view displayed a list of customers. Supposed that your default view was a grid listing of those customers. What if you wanted to show them as tiles that could be rearranged? That would probably be best done in a different view. While you would only have one active view at any time, both views would bind to the same view model where you would maintain the data and the state. For example the "selected" customer shouldn't change if the user simply changes views. If you put anything that is outside of the scope of a single view in the code behind, then you have issues of scope and possible coupling between your view(s) and your view model(s). That is the reason to avoid putting code in the code behind. It is easy to say that it is no big deal when you have a 1 to 1 to 1 mapping. But it becomes a big deal when that changes. So the best practice is to avoid it so you don't have to go back and refactor if something changes. And... that really answers the questions about dependency properties. DP's are used by the binding system to hook-up properties between two classes for automatic synchronization. If you are going to bind two properties (which is what you are doing with the selected row on the treeview and the corresponding property on the view model) then ONE of them has to be a dependency property. So a DP hooked to a DP will work. A DP hooked to a regular property will work. But a regular property hooked to a regular property will not work. The binding framework in this case, can't resolve the property name raised in the propertychanged event because the framework uses the dependency property system to resolve the property names and update the values. The DP system is a static class so there is one instance of it for your appl

                                K Offline
                                K Offline
                                Kevin Marois
                                wrote on last edited by
                                #15

                                First, not apology needed. I'm not offended. On the contrary, I don't mind being educated from time to time So I've read about half of this so far. I'm trying to digest it. It's one of the better explanations of DP's I've read so far. So I created a 5 minute sample app[^]. The goal is to have the Main Window know when a Client in the user control is selected. I learn best by doing, but I'm clearly both confused & wrong. Can you show me where the DP(s) go here and how to wire them up? Let me finish your response and I'll reply soon. Many thanks!

                                If it's not broken, fix it until it is

                                J 2 Replies Last reply
                                0
                                • K Kevin Marois

                                  First, not apology needed. I'm not offended. On the contrary, I don't mind being educated from time to time So I've read about half of this so far. I'm trying to digest it. It's one of the better explanations of DP's I've read so far. So I created a 5 minute sample app[^]. The goal is to have the Main Window know when a Client in the user control is selected. I learn best by doing, but I'm clearly both confused & wrong. Can you show me where the DP(s) go here and how to wire them up? Let me finish your response and I'll reply soon. Many thanks!

                                  If it's not broken, fix it until it is

                                  J Offline
                                  J Offline
                                  Jason Gleim
                                  wrote on last edited by
                                  #16

                                  I fixed up your app to add a singleton class that will hold the currently selected client. Download it here[^]. You will see that in the classes folder I added a new class. It implements the singleton pattern and has a single property... SingletonClient. In the main view model and the client view model, I changed the SelectedClient property to use the new SingletonClient property of the new singleton class. In this way we are using a third-party class (with a single instance) to hold the currently selected client. Since we are doing this, we break the automatic binding support between the VM and the control. This is because the control will bind to the instance of the selected client rather than to the property itself. The fix is easy, we simply hook the PropertyChanged event on the singleton class from each view model that uses it. Inside that handler we check to see if the property that was changed is the one we are interested in. If it is, we manually raise PropertyChanged for the desired property on EACH viewmodel so the controls in each view get notified. I added the same property to the MainViewViewModel and created a text block on the main view that will show you the name of the client that is currently selected. I also declared the main view model in xaml so you can see how to do that rather than in the code behind. :-) You will see that the text block at the top of the main view is bound to the selected client property on the main view model and uses the path to get the name and display it. You will also see that your client view is untouched illustrating how we can keep things separated yet still pass information via a third-party that both view models agree on. If you were unit testing this, you would simply mock the singleton class allowing you to still test each viewmodel in isolation.

                                  1 Reply Last reply
                                  0
                                  • K Kevin Marois

                                    First, not apology needed. I'm not offended. On the contrary, I don't mind being educated from time to time So I've read about half of this so far. I'm trying to digest it. It's one of the better explanations of DP's I've read so far. So I created a 5 minute sample app[^]. The goal is to have the Main Window know when a Client in the user control is selected. I learn best by doing, but I'm clearly both confused & wrong. Can you show me where the DP(s) go here and how to wire them up? Let me finish your response and I'll reply soon. Many thanks!

                                    If it's not broken, fix it until it is

                                    J Offline
                                    J Offline
                                    Jason Gleim
                                    wrote on last edited by
                                    #17

                                    One thing I forgot to mention is that to use a DP, you have to have a class that descends from the DependencyObject class. This means your class where you would use a DP would have to inherit from DependencyObject, Control, or some other subclass. In your sample, you would have to make ViewModelBase inherit from DependencyObject to be able to create DP's on your view models. This isn't really the normal way you would do it as DP's are typically on controls. If you were creating your own control then it would be appropriate to make the properties of that control DP's.

                                    K 2 Replies Last reply
                                    0
                                    • J Jason Gleim

                                      One thing I forgot to mention is that to use a DP, you have to have a class that descends from the DependencyObject class. This means your class where you would use a DP would have to inherit from DependencyObject, Control, or some other subclass. In your sample, you would have to make ViewModelBase inherit from DependencyObject to be able to create DP's on your view models. This isn't really the normal way you would do it as DP's are typically on controls. If you were creating your own control then it would be appropriate to make the properties of that control DP's.

                                      K Offline
                                      K Offline
                                      Kevin Marois
                                      wrote on last edited by
                                      #18

                                      Thank you I am out right now. I'll grab & digest later tonight. Thank you sir!

                                      If it's not broken, fix it until it is

                                      1 Reply Last reply
                                      0
                                      • J Jason Gleim

                                        One thing I forgot to mention is that to use a DP, you have to have a class that descends from the DependencyObject class. This means your class where you would use a DP would have to inherit from DependencyObject, Control, or some other subclass. In your sample, you would have to make ViewModelBase inherit from DependencyObject to be able to create DP's on your view models. This isn't really the normal way you would do it as DP's are typically on controls. If you were creating your own control then it would be appropriate to make the properties of that control DP's.

                                        K Offline
                                        K Offline
                                        Kevin Marois
                                        wrote on last edited by
                                        #19

                                        Ok, so I looked at your code a few times and re-read this post. I understand what you've done here. Thanks for teaching me something. I do have some questions. It seems to me that this is A LOT of code just to build a stand alone user control. Basically, there are now 5 components involved just to tell when the user clicked a list item in the user control. So really this isn't 'stand-alone' at all. In order to make it work there would have to be the singleton class, the User Control, and the host for the control. And, there's duplicate code in some places. Again, I do get what you've done, but I can't believe that it takes this much effort to produce a stand alone user control. Have I missed something here?

                                        If it's not broken, fix it until it is

                                        J 1 Reply Last reply
                                        0
                                        • K Kevin Marois

                                          Ok, so I looked at your code a few times and re-read this post. I understand what you've done here. Thanks for teaching me something. I do have some questions. It seems to me that this is A LOT of code just to build a stand alone user control. Basically, there are now 5 components involved just to tell when the user clicked a list item in the user control. So really this isn't 'stand-alone' at all. In order to make it work there would have to be the singleton class, the User Control, and the host for the control. And, there's duplicate code in some places. Again, I do get what you've done, but I can't believe that it takes this much effort to produce a stand alone user control. Have I missed something here?

                                          If it's not broken, fix it until it is

                                          J Offline
                                          J Offline
                                          Jason Gleim
                                          wrote on last edited by
                                          #20

                                          You are correct that there are better ways to do this. I was building off of your example... not following the cleanest way to do it. Plus, that is sort of a moving target. What you think may be the cleanest way to do it I may think isn't. So my goal was to show you one way of achieving what you wanted using the framework you had setup. The driving factor for my example is that you have a sub-view which you put into the content of the grid in the main view. You create a view model for both the host (main) view and the sub-view. The key thing here is to understand that despite declaring the sub-view as a 'user control' it isn't a control in the traditional sense of the word. That is why DP implementation is a bad choice in this situation. In fact, I hate the "user control" terminology because I think it muddies the waters. They should have called is a "user view" instead but since the class inherits from Control I can understand the naming. So your demo had a main view and a sub view both with view models attached to them. In order to communicate between those two view models in a way that doesn't create a dependency between them requires a third party. That could be command classes, a static or singleton class (as I demonstrated), and a messaging facility. The specifics aren't as important as choosing what is right for your situation and avoiding a dependency between the view models. Circling back around I think I'm understanding where you want to go with this and where we are missing the mark. I think you want the picker to be a CUSTOM CONTROL so you can put it on the main page and have access to the selected item as a property on that control. That is very different than the approach you took in the demo app. The architecture with the views and view models threw me. A custom control actually has nothing to do with MVVM or view models but rather is a marriage of a code file that inherits from control and a xaml template that skins the control typically defined in /Themes/generic.xaml. In this case you can add properties and methods to the class to create the behaviors you want that control to have. That is the time to use dependency properties... but they go on the control class. Custom controls aren't for the faint of heart. There are a number of required moving parts and some very specific requirements. I've got a three part article series that takes you from a blank project to a working custom control but it is still in draft status. I'll try to hurry up and get it published. It would be a good read

                                          K 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups