1

I am creating a user control (a textbox that only accepts integers). The control has to have properties to specify max/min values and whether to allow negative values etc.). I am using MVVM, in my view I have public properties e.g.

const string EXAMPLE = "Example";

string example;

public string Example
{
    get { return example; }
    set
    {
        if (value == example) return;
        example = value;
        OnPropertyChanged(EXAMPLE);
    }
}

These properties are in my View so that someone using the control will be able to easily set them. In my ViewModel I have an identical property, I need these properties to be bound together so that they and their backing fields always have the same value. I hate the code repetition too.

To be honest the whole approach feels wrong and usually that is a good indication that I am approaching the whole thing from the wrong direction or misunderstanding something fundamental.

I have used WPF before but this is a first attempt at a custom control.

mark_h
  • 5,233
  • 4
  • 36
  • 52

2 Answers2

2

There is no MVVM in a Custom Control.

Any Control is only in the View layer. So what you need to do is expose relevant DP to a consumer that you have no knowledge of.

In the Custom Control you need to define your Control behavior, how it reacts to change in DP value and what should be available to a consumer. In the default Template you define how you want to display this Control.

The consumer may want to set or get some dp values so he'll have to bind your Custom Control'dp to a property in his ViewModel but that's up to him.

nkoniishvt
  • 2,442
  • 1
  • 14
  • 29
2

The first thing I want to make sure is that you're truly trying to make a CustomControl and not a UserControl. I believe this question basically is the same as yours except worded differently.

A UserControl lends itself to the MVVM pattern way more readily than a CustomControl because you would have a .xaml (and .xaml.cs) file along with a .cs file to serve as the ViewModel. On the other hand, a CustomControl is never done with MVVM, as the visual appearance (view) is defined and overridable via a ControlTemplate.

Since you said you have a View and ViewModel, let's think about how you would achieve the behavior you want with your textbox. Your textbox will have to validate and reject user input outside the range of values you desire. This means your View code-behind has to have properties and logic that control the restrictions in the input values of the textbox defined in your View. You have already violated MVVM here.

When you said you have a View, that makes me think you're writing a UserControl. But your requirements (a custom behavior for textbox) suggest that you really need a CustomControl, for which you do not use MVVM.

If you agree that you need a CustomControl, here's a quick and dirty example:

 public class RestrictedTextBox : TextBox
 {
    public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(int), typeof(RestrictedTextBox), new PropertyMetadata(int.MaxValue));

    public RestrictedTextBox()
    {
        PreviewTextInput += RestrictedTextBox_PreviewTextInput;
    }

    public int MaxValue
    {
        get
        {
            return (int)GetValue(MaxValueProperty);
        }
        set
        {
            SetValue(MaxValueProperty, value);
        }
    }


    private void RestrictedTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
    {
        int inputDigits;
        RestrictedTextBox box = sender as RestrictedTextBox;
        if (box != null)
        {

            if (!e.Text.All(Char.IsDigit))
            {
                // Stops the text from being handled
                e.Handled = true;
            }
            else if (int.TryParse(box.Text + e.Text, out inputDigits))
            {
                if (inputDigits > MaxValue)
                    e.Handled = true;
            }
        }
    }
}

XAML Usage:

    <local:RestrictedTextBox MaxValue="100"></local:RestrictedTextBox>
Community
  • 1
  • 1
Rowbear
  • 1,619
  • 12
  • 15