【问题标题】:WPF ReadOnly Dependency Properties using MVVM使用 MVVM 的 WPF 只读依赖属性
【发布时间】:2010-12-17 11:33:18
【问题描述】:

我最近重写了 DevXpress WPF 网格,为自己提供了一个 SelectedObject 属性,我可以从松散绑定的 ViewModel 中访问该属性。

我创建了一个 SelectedObject 依赖属性,并将其绑定到我的 XAML 中的 OneWayToSource。

一切正常,但如果我尝试将其设为 ReadOnly(为了完整性),我会收到编译错误并说我无法绑定到 ReadOnly 属性。下面的代码可以编译,我已经包含(但已删除)我在尝试获取属性 ReadOnly 时一直在尝试的位。

有人可以帮忙吗?

我的重写控件的依赖属性如下所示:

  //public static readonly DependencyPropertyKey SelectedRowKey = DependencyProperty.RegisterReadOnly("SelectedObject", typeof(object), typeof(MyGrid), new PropertyMetadata(null));
//public static readonly DependencyProperty SelectedObjectProperty = SelectedRowKey.DependencyProperty;

public readonly static DependencyProperty SelectedObjectProperty = DependencyProperty.Register("SelectedObject", typeof(object), typeof(MyGrid), new PropertyMetadata(null));

public object SelectedObject
{
    get
    {

        return GetValue(SelectedObjectProperty);
    }
    set
    {
        throw new NotImplementedException();
    }
}

XAML 是:

 <StackPanel>
  <devxgrid:MyGrid AutoPopulateColumns="True" DataSource="{Binding Animals}" SelectedObject="{Binding MyObject, Mode=OneWayToSource}" Width="300" Height="300">
    <devxgrid:MyGrid.View>
        <MyGrid:TableView AllowEditing="False" Name="GridView" AutoWidth="True" />
    </devxgrid:MyGrid.View>
 </devxgrid:MyGrid>
</StackPanel>

【问题讨论】:

    标签: wpf mvvm binding dependency-properties


    【解决方案1】:

    您正在尝试在 XAML 中设置 SelectedObject 属性。如果是只读的,怎么设置呢?

    编辑:对不起,我的错。刚刚意识到你正在尝试做什么,你是对的,它应该工作。但是,WPF 不支持这种情况,至少在 3.5 中。

    编辑 2:刚刚签入 .NET 4 和相同的故事。

    顺便说一句,如果您被其他人的只读 DP 卡住,而您正试图将其“推入”虚拟机,您可以使用附加行为来解决此问题。例如,假设您希望您的 VM 知道您的视图的 ActualWidthActualHeight 属性。您可以编写一个SizeWatcherBehavior 附加到FrameworkElement 并监听大小变化。检测到时,这些大小更改会推送到您的 VM 可以绑定到的读/写附加属性:

    <Grid local:SizeWatcherBehavior.Watch="True"
        local:SizeWatcherBehavior.Width="{Binding WidthOnVM, Mode=OneWayToSource}"
        local:SizeWatcherBehavior.Height="{Binding HeightOnVM, Mode=OneWayToSource}"/>
    

    【讨论】:

    • 感谢您的帮助肯特 - 不幸的是,我不认为我可以在没有 DP 的情况下使用观察者,但很高兴知道这样的事情存在!无论如何,我的程序都可以工作,我只是讨厌离开那个'throw new NotImplementedException();' - 它不是“破窗”,但离它不远!但非常感谢您对此进行调查。
    • 我认为这是 WPF 和采用 MVVM 模式的一个严重问题。当源属性为只读时,您可以定义 OneWay 绑定,这很棒。但是当目标 DP 是只读的时,您不能定义 OneWayToSource 绑定。我真的不明白为什么不..
    • 听到 .NET 4 也不支持这一点,我感到非常沮丧。
    • 作为参考,我为此提出了一个问题,今天得到了一些反馈。它不受每个设计的支持,并且不会在最近的将来。 connect.microsoft.com/WPF/feedback/…
    【解决方案2】:

    考虑到大约 2 年前有人问过这个问题,我回答得有点晚了 :)

    我做了一个解决方案,可以动态地将只读依赖属性推送到名为PushBinding 的源,我blogged about here。在您的情况下,它看起来像这样

    <devxgrid:MyGrid AutoPopulateColumns="True"
                     DataSource="{Binding Animals}"
                     Width="300"
                     Height="300">
        <pb:PushBindingManager.PushBindings>
            <pb:PushBinding TargetProperty="SelectedObject" Path="MyObject"/> 
        </pb:PushBindingManager.PushBindings> 
        <!--...-->
    </devxgrid:MyGrid> 
    

    PushBinding 通过使用两个依赖属性,监听器和镜像来工作。侦听器绑定OneWay 到 TargetProperty,并在 PropertyChangedCallback 中将绑定 OneWayToSource 的 Mirror 属性更新为绑定中指定的任何内容。

    Demo Project can be Downloaded Here.
    它包含源代码和简短的示例用法,如果您对实现细节感兴趣,请访问my WPF blog

    【讨论】:

      【解决方案3】:

      我们正在开发一个自定义控件库,我们的一位用户提交了一项功能请求,将我们的一个 DP 从只读转换为读写,因为他确实遇到了与您相同的问题 - 无法在其中绑定 OneWayToSource MVVM 场景。

      当然,我们没有让那个 DP 读写。

      在这种情况下使用附加属性/行为是一个巨大的开销。最简单的解决方法是在后面的代码中处理“SelectedObjectChanged”事件,并在后面的代码中设置要绑定到“SelectedObject”DP 的属性。

      在我们看来,这种“处理事件并直接从 VM/DataContext 调用代码”的方法不会以任何方式破坏 MVVM,因为 ViewModel 仍然不了解 View。

      【讨论】:

      • 强迫人们在背后编写代码本质上会破坏 mvvm。
      【解决方案4】:

      否则,我们中间的纯粹主义者会期望真正的只读DependencyProperty 场景在理想情况下应该按预期工作。但是对于明显的 WPF 单向和双向数据绑定期望,我同意这些观点。

      但是,我在 DependencyObject 视图模型中通过提供完整的 DependencyProperty 解决了这个问题,但只提供了一个公开我想要的细节的 get-only 属性。在 WPF MVVM 意义上不是真正的只读,但由于我选择不实现 setter,所以它适用于我的目的。

      我同意其他人的观点,任何比最严格意义上的破坏 MVVM 的代码还要多。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-19
        相关资源
        最近更新 更多