2

I am confused about where I put a dependency property when building a WPF application using the MVVM pattern. Does it go in the Model or the ViewModel?

Edit

After looking at early answers (thanks for those), I find that I am still confused, so I am giving more detail to help someone explain this to me.

I have a class called Station. It is used by surveyors and civil engineers to represent the length along a road. For the most part, a Station is just a double, but it has a few decorations. First off, the format is different. When distance along is greater than 100 feet, we add a + symbol as another way to format it. So 1234.56 feet down the road we might have Station 12+34.56. (I will skip the other decorations since this one is good enough for my point.)

Thus the logic for the special formatting lives in Station, a class in the Model. I want a TextBox in the View to take user input of 1234.56 and coerce it to a text value of "12+34.56". So I want a TextBox to give the user access to a value in the Model, so it needs to be a dependency property. (That is correct, isn't it?) But the business logic for coercing/parsing/understanding how to go back and forth between a TextBox and a Station should live in the Station class. (Right?)

Furthermore, I will later want to give the user the ability to set the station value by clicking on a graphical drawing of the road, including dynamically updating the value as the mouse moves and locking the value in upon issuing a data point. (Now you see why I tried to keep this brief.)

So is this not something that I would want to make a dependency property, especially with the dynamic data point possibly getting involved later? If not, how do I hook a text box item to a station using MVVM? (I really have researched this a lot before asking my question, but with no success.)

  • Paul
philologon
  • 2,093
  • 4
  • 19
  • 35
  • Related: http://stackoverflow.com/questions/11548952/wpf-dependency-property-mvvm Rachel's answer is good for your question I believe. – Avada Kedavra Sep 03 '12 at 22:53
  • Avada Kedavra: I looked at that, but it does not seem to be getting at the same question that I have, so I edited my op for more clarity. – philologon Sep 03 '12 at 23:36

2 Answers2

3

Typically, you wouldn't use Dependency Properties in either the ViewModel or the Model.

Dependency properties are really intended for View-related functionality only. You'd bind a View's DP to a ViewModel, which would instead implement INotifyPropertyChanged.

Putting a DP into the ViewModel or the Model itself would actually violate one of the main goals of MVVM, as this would couple the user interface technology (WPF) to your Model or application-specific types.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Reed Copsey: I see your point (please review my edited op). But when I read something like Petzold's _3D Programming For Windows_, pp 257--270, so far as I can tell it looks like his custom dependency property is in his model (and he does not implement a VM) -- so far as I can tell. – philologon Sep 03 '12 at 23:38
  • @philologon "So I want a TextBox to give the user access to a value in the Model, so it needs to be a dependency property" - Not true. You can bind from the TextBox to a property in a class that implements `INotifyPropertyChanged`. Also - Petzold's book is about using WPF, but **not** about using WPF via MVVM. He doesn't really do anything MVVM related in his book, but more just makes things work "quick and dirty". For MVVM, I'd look elsewhere (ie: http://reedcopsey.com/series/windows-forms-to-mvvm/) – Reed Copsey Sep 03 '12 at 23:50
  • I agree with Reed. DP's are for user controls and applying binding in XAML. – Ed Chapel Sep 03 '12 at 23:54
  • Reed, I followed the link to your webpage and series. I plan to read it soon. I really appreciate your help. Thanks a bunch. – philologon Sep 04 '12 at 01:00
2

With MVVM, you prefer INotifyPropertyChanged properties over DependencyProperties.

Your Station class should implement the property with INotifyPropertyChanged. Your TextBox binding should use a converter to present and read the value in the format you wish.

public class Station : INotifyPropertyChanged
{
    private decimal _value;
    public decimal Value
    {
        get { return _value; }
        set
        {
            if (_value == value) return;

            _value = value;
            NotifyPropertyChanged("Value");
        }
    }
    /* INotifyPropertyChanged implementation */
}

public class StationConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string formattedValue = // Add the plus here
        return formattedValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string numericValue = // Parse the optional '+' out of the value
        decimal stationValue = decimal.Parse(numericValue);
    }
}

XAML:

<UserControl.Resources>
    <StationConverter Key="StationConverter" />
    <TheViewModel Key="TheVM" />
<UserControl.Resources>

<TextBox Text="{Binding Path=Station.Value, Source={StaticResource TheVM}, Converter={StaticResource StationConverter}, Mode=TwoWay}"/>
Ed Chapel
  • 6,842
  • 3
  • 30
  • 44