【问题标题】:Inner property of ItemsControl not updating when bound on ItemsSourceItemsControl 的内部属性在绑定到 ItemsSource 时未更新
【发布时间】:2011-04-21 19:12:40
【问题描述】:

我有一个如下所示的 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
    }

【问题讨论】:

    标签: silverlight mvvm binding


    【解决方案1】:

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

    谷歌搜索得到了我this post,你可能想看看。

    但我个人会查看您的 CanExecute 和您的 ViewCommand 并确保它仅在 ViewEnabled == true 时运行

    【讨论】:

    • 好吧,当我以 2 方式进行绑定时,它实际上会禁用所有链接。第一遍似乎是正确的,然后第二遍禁用所有这些。我知道它被禁用时的功能。如果是,我的 ViewCommand 方法不会运行。
    • 感谢您的帮助。你肯定给我指明了正确的方向。
    【解决方案2】:

    当我使用 MVVM 时,在我的属性的设置器中,我有一个名为 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, ...} 希望这会有所帮助。

    【讨论】:

    • 在您的示例中,您将处理程序设置为 PropertyChanged,然后以相同的方式调用它。 Dispatcher.BeginInvoke 是强制它在 UI 线程上运行,这防止了我收到的错误。我在绑定中添加了显式路径,但无济于事。不过感谢您的帮助!
    • 所以我的下一个问题是,您什么时候将其设置为 false?您是否在实例化时将其设置为 false ?尝试做... private bool _viewEnabled = false;抱歉,我在这方面帮不上什么忙。似乎是一个不应该成为问题的简单问题。在我看来是对的。另外,我不熟悉 cmd:Click.Command 和 cmd:Click.Parameter,但是传递绑定是否有可能会影响 IsEnabled 绑定?
    • 我在设置 ViewEnabled 属性的位置添加了代码。
    【解决方案3】:

    听从 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.Commandcmd:Click.CommandParameter xml。从那个切换到 xaml 中的 CommandCommandParameter 属性,就像我在切换到 RelayCommand 后所做的那样,是什么实际上让它工作了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-10
      • 2017-04-07
      • 1970-01-01
      相关资源
      最近更新 更多