【问题标题】:Force reevalution of guard methods in Caliburn MicroCaliburn Micro 中保护方法的强制重新评估
【发布时间】:2011-09-30 15:30:54
【问题描述】:

我有一个 ItemsControl,它在每个项目中都有一个上移、下移和删除按钮(通过模板)。我的 ItemsControl 源绑定到项目集合,这些项目是模型 DataContracts/POCO(不是 VM)。

我在我的主页的视图模型中附加了一个 Caliburn 消息处理程序。

<Button cal:Message.Attach="MoveUp($dataContext)" >Up</Button>
<Button cal:Message.Attach="MoveDown($dataContext)" >Down</Button>

我相信我必须明确使用 cal:Message.Attach 而不是依赖约定,因为我在我的 ItemTemplate 中。

查看模型:

    ObservableCollection<Item> MyCollection = new ObservableCollection<Item>();  
    //Item class is simple -- only has a string Name property 

    public bool CanMoveUp(Item item)
    {
        var index = MyCollection.IndexOf(item);
        return index > 0;
    }

    public void MoveUp(Item item)
    {
        var index = MyCollection.IndexOf(item);
        if (index > 0)
        {
            MyCollection.Remove(item);
            MyCollection.Insert(index - 1, item);
        }
    }           


    public bool CanMoveDown(Item item)
    {
        var index = MyCollection.IndexOf(item);
        return index > -1 && index < class1.Count - 1;
    }

    public void MoveDown(Item item)
    {
        var index = MyCollection.IndexOf(item);
        if (index > -1 && index < class1.Count - 1)
        {
            MyCollection.Remove(item);
            MyCollection.Insert(index + 1, item);
        }
    }

第一项的向上按钮最初是禁用的。当我向下移动第一项时,第二项成为第一项,但它的向上按钮不会自动禁用。如何强制重新评估 CanMoveUp 保护方法?

【问题讨论】:

  • 关于显式附加的注释,带有内联 ItemTemplate 是的,您确实需要显式,如果您在单独的“视图”控件中定义模板,则绑定引擎将能够确定模板和因此你得到应用的标准约定......

标签: silverlight mvvm caliburn.micro


【解决方案1】:

在您的MoveUpMoveDown 方法中,您可以使用NotifyOfPropertyChanged(() =&gt; this.CanMoveUp);(或this.CanMoveDown,视情况而定)通知用户界面CanMoveUp/Down 的绑定已失效。

这是假设您的 ViewModel 应该派生自 ScreenConductorPropertyChangedBase

更新

您要做的是重构代码以将ListBoxSelectedItem 绑定到您的视图模型上Item 类型的属性。事实上,Caliburn.Micro 会为您执行此操作,例如,如果您的 ListBox 有一个 x:Name="Items",它会查找名为 SelectedItem 的属性(它还会搜索其他约定)。然后,您的 CanMoveUp/Down 方法可以是属性,而不是检查 SelectedItem 属性,因此您可以使用 NotifyOfPropertyChanged() 使这些绑定无效。

【讨论】:

  • 谢谢,但 NotifyOfPropertyChanged(() => this.CanMoveUp);不会编译,因为我的守卫是带参数的方法,而不是属性。我也试过 NotifyOfPropertyChanged(() => this.CanMoveUp(i));但 Caliburn 在运行时抛出异常。
  • 对不起,你说的很对,我写的时候已经晚了。我已经更新了我的答案。
  • ItemsControl 没有 SelectedItem - 开始尝试使用 ListBox。我认为这个解决方案可能有点脆弱——我们依赖于在 ViewModel 处理按钮单击之前选择 ListBoxItem。我也不认为单一的无参数 CanMoveUp 方法可以工作——当第二个项目上移到第一个位置时,我需要重新评估第一个和第二个项目的 CanMoveUp,一个返回 true,另一个返回 false。如果我们只是处理 SelectedItem,则不会发生这种情况。现在每行尝试一个新的虚拟机。
  • 你说得对,ListBox 就是这样。我不确定你的其他观点是什么意思。如果没有 SelectedItem,则可以使上移/下移不可用。即在 SelectedItem 设置器中,CanMoveUp/Down 上的 NotifyOfPropertyChange,他们可以检查 this.SelectedItem == null 并返回 false。至于对第 1 项和第 2 项的重新评估,再次不确定您的意思。当调用 MoveUp/Down 时,您可以在 CanMoveUp/Down 上进行通知,他们将移动项目,然后检查当前选中的项目(this.SelectedItem)是否在集合中的第一个/最后一个。
【解决方案2】:

我最终将我的 Item 类提升为一个成熟的 ViewModel。我使用 IoC / MEF 以便 Item 类可以找到它的容器,因此它可以判断它是容器中的第一个还是最后一个项目。如果我需要强制重新评估,我创建了一个重新评估保护属性的方法:

public void ReevaluateButtons()
{
    NotifyOfPropertyChange(() => CanMoveDown);
    NotifyOfPropertyChange(() => CanMoveUp);
}

仍然不知道是否还有办法强制重新评估守卫方法

NotifyOfPropertyChange(() => CanMoveDown(item));

【讨论】:

    猜你喜欢
    • 2011-07-29
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 2020-06-01
    • 2015-09-22
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    相关资源
    最近更新 更多