开发者

Force reevalution of guard methods in Caliburn Micro

I have an ItemsControl which has a move up, move down, and delete button in each item (via template). My ItemsControl source binds to a collection of Items which are model DataContracts/POCOs (not VMs).

I've attached a Caliburn message handler in my main page's view model.

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

I believe I had to be explicit with cal:Message.Attach and not rely on convention because I was within my ItemTemplate.

View Model:

    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);
        }
    }

The first item's up button is initially disabled. When I move down the first item, the 2nd item becomes the first item, but its up button is not automatically disabled. How do I force reevaluation of the CanMoveUp guard method?


In your MoveUp and MoveDown methods, you can notify the UI that the bindings for CanMoveUp/Down have been invalidated using NotifyOfPropertyChanged(() => this.CanMoveUp); (or this.CanMoveDown as appropriate).

This is assuming your ViewModel derives from Screen, Conductor, or PropertyChangedBase which it should.

Update

What you'll want to do is refactor the code to bind the SelectedItem of the ListBox to a property on your view model of type Item. In fact, Caliburn.Micro will do this for you, if your ListBox has an x:Name="Items" for example, it will look for a property called SelectedItem (there are other conventions too that it searches for). Then, your CanMoveUp/Down methods can be properties instead that check the SelectedItem property, and therefore you can use NotifyOfPropertyChanged() to invalidate those bindings.


I ended up promoting my Item class to a full fledged ViewModel. I used IoC / MEF so that the Item class could find its container, so it could tell if it was the first or last item in the container. If I need to force reevaluation, I created a method that reevaluates guard properties:

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

Still don't know if there is yet a way to force reevaluation of guard methods

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜