【问题标题】:Undo journaling: focusing the control being undone撤消日志:关注正在撤消的控制
【发布时间】:2010-10-25 13:11:56
【问题描述】:

我正在为我的 WPF 数据输入屏幕编写撤消日志,它将跟踪所有控件的更改。当用户选择撤消时,我不仅要恢复最新的更改,还要将焦点放回其值正在恢复的控件中。我正在努力寻找重新集中注意力的最佳方式。

我的 ViewModel 将是处理撤消日志的部分:ViewModel 的属性设置器将在更新 DataModel 之前捕获一些“之前”状态。无论如何,“之前”状态需要包含足够的信息,以便我能够稍后将注意力放回原处。

为了说明,假设有两个数据输入字段:地址和城市。 ViewModel 有一个属性,View 有一个 TextBox,每个都绑定到相应的 ViewModel 属性。

让我们按照用户刚刚在“地址”字段中输入值,然后单击“城市”字段的示例进行操作。我正在使用默认的 UpdateSourceTrigger.LostFocus 行为,因此当地址文本框失去焦点时,地址更改会被保存。到目前为止,我对如何解决这个问题有三个不同的想法,但我对 WPF 的了解不够多,无法知道如何使它们中的任何一个工作。

  1. 我可以忘记 MVVM 样式的数据绑定,并挂钩编辑控件的 LostFocus 事件(或添加附加行为,或制作包装 TextBox 的自定义控件,或者...)。在 LostFocus 事件处理程序中,我可以创建一个撤消帧,其中包含对事件发送者的引用。稍后,在撤消之后,我只关注我保存了其引用的控件。这可能是我在 WinForms 中所做的,但在 WPF 中我宁愿坚持使用 ViewModel 模式——我宁愿让日志逻辑存在于 ViewModel 中而不是 View 中,以确保可测试性。所以这个选项不是我的第一选择。

  2. 在我的 ViewModel 的属性设置器中,我可以捕获正在设置的 ViewModel 属性的名称(在本例中为“地址”),并将该名称存储在撤消框架中。稍后,在撤消时,我可以遍历视图中的所有控件,寻找我能找到的第一个绑定到名为 Address 的属性的控件。一旦我找到一个这样的控制,我就会把重点放在它上面。这足以满足我的需要,因为我不希望将多个控件绑定到同一个 ViewModel 属性。问题是这需要深入研究绑定表达式,这是我不知道该怎么做的事情。 (如果我重构,它还会引入更多基于名称的后期绑定。)

  3. 当我的 ViewModel 将更改添加到撤消堆栈时,它可以要求 View 层(通过接口)创建一个知道哪个控件具有焦点的 Memento。在撤消时,日记会要求视图恢复该备忘录。这里的问题是,当我的 ViewModel 的属性被设置并添加撤消框架时,键盘焦点已经移动到 City TextBox,因此“创建纪念品”需要比“哪里”更棘手当前的键盘焦点”,我不知道如何完成这个技巧。

有人对上述任何工作有任何建议,或者有可能更好的替代方法吗?

【问题讨论】:

  • 我认为您最终将不得不打破 MVVM 模式,因为您的 ViewModel 与您的 View 深度耦合。
  • 您对实现这一点的方法有什么建议,更适合 MVVM 吗?我只是不希望用户点击撤消并且不知道刚刚更改了什么(因为刚刚撤消的控件可能会滚出屏幕)。

标签: wpf mvvm focus undo


【解决方案1】:

我将从您的第二种方法开始。但是,我不会深入研究绑定列表,而是将控件的高亮属性硬编码为 VM 属性。

例如,这是我的虚拟机:

public class VM
{
    public double Price { get; set; }
    public bool PriceHighlighted { get; set; }
}

然后,将 Price 属性绑定到 TextBox,并将 TextBox 的背景绑定到 PriceHighlighted(使用值转换器)。现在 VM 可以完全控制视图的反应方式。当用户执行“撤消”操作时,VM 可以将所有 xxxHightlighted 设置为 false,但要突出显示的除外。

【讨论】:

  • 有趣的想法。没有回答如何将该字段滚动到视图中的问题,但它肯定是可测试的。
  • 如何滚动视图取决于视图如何使用 VM 提供的信息。例如,如果所有文本框都在绑定到列表视图的集合中,则可以通过设置集合视图的 selectedIndex 来滚动视图。
猜你喜欢
  • 2021-06-01
  • 1970-01-01
  • 2014-04-12
  • 2013-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-06
  • 2018-06-15
相关资源
最近更新 更多