【问题标题】:Where to place the dependency property?在哪里放置依赖属性?
【发布时间】:2012-09-03 22:50:51
【问题描述】:

在使用 MVVM 模式构建 WPF 应用程序时,我对放置依赖属性的位置感到困惑。它是放在 Model 还是 ViewModel 中?

编辑

在查看了早期答案(感谢那些)之后,我发现我仍然很困惑,所以我提供更多细节来帮助有人向我解释这个问题。

我有一个名为 Station 的课程。测量员和土木工程师使用它来表示道路的长度。在大多数情况下,Station 只是一个替身,但它有一些装饰。首先,格式不同。当距离大于 100 英尺时,我们添加一个 + 符号作为另一种格式化方式。因此,在道路下方 1234.56 英尺处,我们可能会有 12+34.56 站。 (我将跳过其他装饰,因为这对我的观点来说已经足够了。)

因此,特殊格式的逻辑存在于模型中的一个类 Station 中。我希望视图中的 TextBox 接受用户输入 1234.56 并将其强制为“12+34.56”的文本值。所以我想要一个 TextBox 让用户访问模型中的一个值,所以它需要是一个依赖属性。 (这是正确的,不是吗?)但是用于强制/解析/理解如何在 TextBox 和 Station 之间来回切换的业务逻辑应该存在于 Station 类中。 (对吧?)

此外,我稍后希望让用户能够通过单击道路的图形图来设置车站值,包括在鼠标移动时动态更新值以及在发布数据点时锁定值。 (现在你明白我为什么要保持简短。)

所以这不是我想要创建一个依赖属性的东西吗,尤其是动态数据点可能会在以后涉及?如果没有,我如何使用 MVVM 将文本框项连接到工作站? (在问我的问题之前,我确实对此进行了很多研究,但没有成功。)

  • 保罗

【问题讨论】:

  • 相关:*.com/questions/11548952/… Rachel 的回答对你的问题很有帮助,我相信。
  • Avada Kedavra:我看过了,但它似乎没有解决我的问题,所以为了更清楚,我编辑了我的操作。

标签: c# wpf mvvm dependency-properties


【解决方案1】:

通常,您不会在 ViewModel 或模型中使用依赖属性。

依赖属性仅适用于与视图相关的功能。您将 View 的 DP 绑定到 ViewModel,而 ViewModel 将实现 INotifyPropertyChanged

将 DP 放入 ViewModel 或模型本身实际上会违反 MVVM 的主要目标之一,因为这会将用户界面技术 (WPF) 耦合到您的模型或特定于应用程序的类型。

【讨论】:

  • Reed Copsey:我明白你的意思(请查看我编辑的操作)。但是当我阅读 Petzold 的 3D Programming For Windows 之类的内容时,据我所知,第 257--270 页,他的自定义依赖属性似乎在他的模型中(而且他没有实现 VM )——据我所知。
  • @philogon “所以我想要一个 TextBox 让用户可以访问模型中的一个值,所以它需要是一个依赖属性” - 不正确。您可以从 TextBox 绑定到实现 INotifyPropertyChanged 的类中的属性。另外 - Petzold 的书是关于使用 WPF,但不是是关于通过 MVVM 使用 WPF。他在他的书中并没有真正做任何与 MVVM 相关的事情,但更多的只是让事情“快速而肮脏”地工作。对于 MVVM,我会寻找其他地方(即:reedcopsey.com/series/windows-forms-to-mvvm
  • 我同意里德的观点。 DP 用于用户控件和在 XAML 中应用绑定。
  • Reed,我点击了您的网页和系列的链接。我打算很快读完。我真的很感谢你的帮助。非常感谢。
【解决方案2】:

使用 MVVM,您更喜欢 INotifyPropertyChanged 属性而不是 DependencyProperties。

您的Station 类应使用INotifyPropertyChanged 实现该属性。您的TextBox 绑定应使用转换器以您希望的格式呈现和读取值。

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}"/>

【讨论】:

  • 感谢您的解释。您在这里解释的内容比四本书所能做的还多。