View中的属性必须与ViewModel中的相同属性匹配

时间:2016-01-19 15:27:23

标签: c# wpf mvvm

我正在创建一个用户控件(一个只接受整数的文本框)。控件必须具有指定最大/最小值以及是否允许负值等的属性。我正在使用MVVM,在我看来,我有公共属性,例如

const string EXAMPLE = "Example";

string example;

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

这些属性位于我的视图中,因此使用该控件的人可以轻松设置它们。在我的ViewModel中,我有一个相同的属性,我需要将这些属性绑定在一起,以便它们和它们的支持字段始终具有相同的值。我也讨厌代码重复。

说实话,整个方法都是错误的,通常这表明我正在从错误的方向接近整个事情或误解一些基本的东西。

之前我使用过WPF,但这是自定义控件的第一次尝试。

2 个答案:

答案 0 :(得分:2)

自定义控件中没有MVVM。

任何控件仅在视图层中。因此,您需要做的是将相关的DP暴露给您不了解的消费者。

在自定义控件中,您需要定义控件行为,它如何响应DP值的变化以及消费者可以使用的内容。在默认模板中,您可以定义要显示此控件的方式。

消费者可能想要设置或获取一些dp值,因此他必须将自定义Control'dp绑定到他的ViewModel中的属性,但这取决于他。

答案 1 :(得分:2)

我想要确保的第一件事是你真正想要制作CustomControl而不是UserControl。我相信question基本上与你的相同,但措辞不同。

UserControl比CustomControl更容易使用MVVM模式,因为你有.xaml(和.xaml.cs)文件以及.cs文件作为ViewModel。另一方面,CustomControl永远不会使用MVVM,因为可视外观(视图)是通过ControlTemplate定义和覆盖的。

由于您说您有View和ViewModel,让我们考虑如何使用文本框实现所需的行为。您的文本框必须验证并拒绝所需值范围之外的用户输入。这意味着您的View代码隐藏必须具有控制View中定义的文本框输入值中的限制的属性和逻辑。你已经在这里违反了MVVM。

当你说你有一个View时,这让我觉得你在写一个UserControl。但是你的要求(文本框的自定义行为)表明你确实需要一个不使用MVVM的CustomControl。

如果您同意需要CustomControl,这是一个快速而肮脏的例子:

 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用法:

    <local:RestrictedTextBox MaxValue="100"></local:RestrictedTextBox>