Stephen Drew
Stephen Drew

Reputation: 1422

WPF controls with "invalid" values

I am creating an auto-complete box, which uses a list of valid values (objects, not strings). The objects are bound directly and the box (both text box and drop-down parts) use a DisplayMemberPath to determine what to show as text.

I want the user to be able to type in text - if the text does not match one of the valid values, I want it to remain in the box and be flagged as invalid visually.

Now, when I bind to the view model, obviously I need to set something for this invalid value. I tried setting the value to DependencyProperty.UnsetValue. This gets returned to the VM as null.

If I later want to "clear" my form, I set the VM property to null, but of course this does not filter through to the control, as the value has not changed.

I would have expected the Property system to notice that the new value is null and the old value was UnsetValue and therefore fire the event.

Have I missed something obvious?

Thanks

Upvotes: 1

Views: 705

Answers (2)

hbarck
hbarck

Reputation: 2944

Instead of setting DependencyProperty.UnsetValue, which has a special meaning to the WPF framework, you could create your own marker object for invalid values, like

public static Object Dummy = new Object();

Instead of Object, you should probably use the same class that your valid values have. Now, when you reset the VM, the value will really change, and WPF will notice the difference.

Upvotes: 2

Danny Varod
Danny Varod

Reputation: 18098

A simple and validation-framework independent way of doing this would be to let the VM do the work.

E.g.

public class MyVM : MyBaseVM
{
    private ObservableCollection<Object> _items
        = new ObservableCollection<Object>();
    public ObservableCollection<Object> Items
    {
        get
        {
            return _items;
        }
    }

    private string _text;
    public string Text
    {
        get
        {
            return _text;
        }
        set
        {
            _text = value;
            Validate();

            if (_isValid)
                _model.Text = value;

            NotifyPropertyChanged("Text");
        }
    }

    private bool _isValid = true;
    public bool IsValid
    {
        get
        {
            return _isValid;
        }
        private set
        {
            _isValid = value;
            NotifyPropertyChanged("IsValid");
        }
    }

    private void Validate()
    {
        IsValid = _items.Any(i =>
            i.ToString().ToLower() == _text.ToLower().Trim());
    }
}

Upvotes: 0

Related Questions