Question

I am trying to build my application settings page depending on the properties exposed by ViewModel. I'm using .Net 4.0 with MVVM. ViewModel exposes single Collection of "group of setting values". Group represents properties that are dependent on each other and belong to a logical group wrt to domain. Settings page in view is created using DataTemplate like below:-

<DataTemplate x:Key="contentSettingGroup1">
  <TextBlock Text="{Binding Field1Description}" />
  <TextBox Text="{Binding Field1Value, Mode=TwoWay}" Grid.Column="2" />

  <TextBlock Text="{Binding Field2Description}"  />
  <TextBox Text="{Binding Field2Value, Mode=TwoWay}" Grid.Column="6" />
</DataTemplate>

<DataTemplate DataType="{x:Type vm:SettingGroup1}">
  <HeaderedContentControl Header="{Binding}" HeaderTemplate="{StaticResource titleArea}" Content="{Binding}" ContentTemplate="{StaticResource contentSettingGroup1}" />
</DataTemplate>

Then I have a class in ViewModel module to represent the "Group of settings" as below:

public class SettingGroup1 : INotifyPropertyChanged, IDataErrorInfo
{
    public double Field1value { get; private set; }
    public double Field2value { get; private set; }

    private double mField1;
    public double Field1value
    {
        get { return mField1; }
        set
        {
            if (mField1 != value)
            {
                mField1 = value;
                RaisePropertyChanged(() => Field1value);
            }
        }
    }

    private double mField2;
    public double Field2value
    {
        get { return mField2; }
        set
        {
            if (mField2 != value)
            {
                mField2 = value;
                RaisePropertyChanged(() => Field2value);
            }
        }
    }

    public string Error
    {
        get { return null; }
    }

    public string this[string property]
    {
        get
        {
            string errorMsg = null;
            switch (property)
            {
                case "Field1value":
                    if (Field1value < 0.0)
                    {
                        errorMsg = "The entered value of Field1 is invalid !";
                    }
                    if (Field1value < Field2value)
                    {
                        errorMsg = "The Field1 should be greater than Field2 !";
                    }
                    break;
            }
            return errorMsg;
        }
    }
}

And finally the viewModel exposes collection of such group of settings:

public ObservableCollection<object> Settings
        {
            get
            {
                var pageContents = new ObservableCollection<object>();
                var group1 = new SettingGroup1();
                group1.Field1.Description = "Description value 1";
                group1.Field1.Value = mValue1;
                group1.Field2.Description = "Description value 2";
                group1.Field2.Value = mValue2;
                pageContents.Add(group1);

                // add other groups of controls
                // ...
                return pageContents;
            }
        }

The Problem: The property setter is called but Data validation is not called whenever UI value is changed. I've tried putting IDataErrorInfo implementation in ViewModel class also but none works. I've to use group of settings as these application settings are used in many projects and we don't want duplicate XAML for each application. Note: The viewmodel is not exposing the property that UI is binding to e.g. Field1Value but exposing an encapsulated object.

Was it helpful?

Solution

You aren't telling your view that the property you're binding to needs to be validated. Use "ValidatesOnDataErrors = true" in your binding.

<TextBox Text="{Binding Field1Value, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Column="2" />
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top