ItemsControl的内部属性在ItemsSource上绑定时不更新

时间:2011-04-21 19:12:40

标签: silverlight mvvm binding

我有一个像以下

的ItemsControl
<ItemsControl ItemsSource="{Binding MyClass.Links}"  >
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Grid d:DesignWidth="450" d:DesignHeight="245" Height="Auto" Width="Auto">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" MinWidth="145"/>
                <ColumnDefinition Width="Auto" MinWidth="179"/>
            </Grid.ColumnDefinitions>
            <HyperlinkButton Content="{Binding ViewName}" IsEnabled="{Binding ViewEnabled, Mode=OneWay}" cmd:Click.Command="{Binding DataSource.ViewCommand, Source={StaticResource DataContextProxy}}" cmd:Click.CommandParameter="{Binding}" Margin="4"/>
        </Grid>
    </DataTemplate>
</ItemsControl.ItemTemplate>

我有一个以下类的ObservableCollection,itemssource被绑定到

public class LinkClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public string ViewName { get; set; }
    private bool _viewEnabled;
    public bool ViewEnabled { 
    get { return this._viewEnabled; }
        set
        {
            if (value != this._viewEnabled)
            {
                this._viewEnabled = value;
                if (this.PropertyChanged != null)
                {
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                          this.PropertyChanged(this, new PropertyChangedEventArgs("ViewEnabled"))
                        );
                }
            }
        }
    }
}

当在视图模型中命中命令时,绑定链接的ViewEnabled被设置为false(禁用我正在查看的视图的链接)。问题是,链接实际上没有被禁用(IsEnabled设置为false)。

所以最后的问题是,为什么这不起作用?我是MVVM和silverlight的新手,所以我希望它很简单。

更新

我将ViewEnabled属性设置为true,除了单击按钮的绑定LinkClass,我将其设置为false。它为每个(更改)触发了PropertyChanged事件,但没有更新UI。我使用绑定运行了一个空的转换器,并且在单击链接时也没有被击中,因此PropertyChanged没有正确冒泡(或者我怀疑它应该正常)。

以下是设置我的LinkClass集合的ViewEnabled属性的代码:

public ICommand ViewCommand
    {
        get {
            return new DelegateCommand<object>(param =>
                {
                    this.ViewSelected((LinkClass)param);
                }); 
        }
    }

    public void ViewSelected(LinkClass link)
    {
                foreach (var containerLink in _myClass.Links)
                {
                    if (containerLink == link)
                        containerLink.ViewEnabled = false;
                    else
                        containerLink.ViewEnabled = true;
                }
        ...other code here
    }

3 个答案:

答案 0 :(得分:1)

实际上它可能会被禁用但是如果你的ViewCommand没有注意到该属性,那么你就会陷入困境。特别是因为看起来该命令是一个附加属性。

谷歌搜索让我this post你想看看。

但我个人会查看您CanExecute的{​​{1}},并确保仅在ViewCommand

时才会运行

答案 1 :(得分:0)

当我使用MVVM时,在我的属性的setter中,我有一个名为NotifyPropertyChanged()的方法,并且会调用它传递属性名称的字符串值。我不确定Deployment.Current.Dispatcher.BeginInvoke(...)是做什么的,但这个方法总是对我有用。

    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;

        if (handler.IsNotNull())
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

所以在我的财产中,我会做类似的事情......

    public Nullable<int> UpdatedBy
    {
        get { return _updatedBy; }
        set
        {
            if (_updatedBy.IsEqualTo(value))
                return;

            _updatedBy = value;
            NotifyPropertyChanged("UpdatedBy");
        }
    }

另外,只是抓住吸管,但尝试放置{Binding Path = ViewEnabled,...} 希望这会有所帮助。

答案 2 :(得分:0)

根据Jose的建议,我查看了我正在使用的ViewCommand(DelegateCommand)的canExecute方法,但是实现该方法并没有解决问题,因为它只运行一次,而不是在更改时运行。我找到了一个示例,建议使用INotifyPropertyChanged类的PropertyChanged事件处理程序来调用DelegateCommand的RaiseCanExecuteChanged()方法。我为所有LinkClass实例执行了此操作,如此处所示为1,然后将其设置为_myClass.Links:

var link = new LinkClass()
                             {
                                 ...
                                 ViewEnabled = true
                             };
                            link.PropertyChanged += new PropertyChangedEventHandler(link_PropertyChanged);
                            return link;

我这样做了,但无济于事。然后我发现这篇博文:DelegateCommand in Prism loses eventhandler and CanExecute never gets called然后我从Prism切换到RelayCommand类,它起作用了!希望这有助于其他人。

<强>更新

实际问题在于使用Prism的 cmd:Click.Command cmd:Click.CommandParameter XAML。正如我在切换到RelayCommand后所做的那样,在xaml中从那里切换到 命令 CommandParameter 属性是什么实际上让它工作。