代码之家  ›  专栏  ›  技术社区  ›  TimothyP

强制数据绑定WPF列表框更新的更好方法?

  •  29
  • TimothyP  · 技术社区  · 16 年前

    我有一个WPF列表框,它绑定到一个可观察的集合, 当集合更改时,所有项都会更新其位置。

    新位置存储在集合中,但UI不会更新。 因此,我添加了以下内容:

        void scenarioItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            ToolboxListItem.UpdatePositions();
            lstScenario.ItemsSource = null;
            lstScenario.ItemsSource = ToolboxListItem.ScenarioItems;
            this.lstScenario.SelectedIndex = e.NewStartingIndex;
        }
    

    通过将ItemsSource设置为null,然后再次绑定它,UI将更新,

    但这可能是非常糟糕的编码:p

    建议?

    7 回复  |  直到 16 年前
        1
  •  76
  •   Gishu    16 年前

    我有一个绑定到类型为的对象属性的列表框 List<MyCustomType>() 我验证了当列表更新时,下面的代码会更新列表框。

    void On_MyObjProperty_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
       MyListBox.Items.Refresh();
    }
    

        2
  •  10
  •   rolling    15 年前

    WPF将项目列表/集合绑定到列表框,但在项目更新后UI不会刷新, 解决了的

    我只是愚蠢。虽然我读了很多关于使用 ObservableCollection<> List<> 可观察收集<&燃气轮机; 是必须使用的,因为 不提供 INotifyCollectionChange 系统所需的接口 ListBox 在集合中的项目更改时更新其显示。

    这是更新的代码:

    private ObservableCollection<StringWrapper> m_AppLog;
    ObservableCollection<StringWrapper> Log { get { return m_AppLog; } }
    

    非常简单,不需要其他任何东西(例如Refresh())。由于ObservableCollection会自行触发更改事件,因此我能够删除不必要的调用:

    // notify bound objects
    OnPropertyChanged("Log");
    

    ObservableCollection 不支持由未创建更新的线程进行更新。因为我的列表(显示最近错误/信息消息的可视日志)可以从不同的线程进行更新,所以我添加了以下内容来调整代码,以确保使用列表自己的调度程序完成更新:

    public void AddToLog(string message) {
        if (Thread.CurrentThread != Dispatcher.Thread) {
            // Need for invoke if called from a different thread
            Dispatcher.Invoke(
                DispatcherPriority.Normal, (ThreadStart)delegate() { AddToLog(message); });
        }
        else {
            // add this line at the top of the log
            m_AppLog.Insert(0, new StringWrapper(message));
            // ...
    

    还要注意 可观察收集<&燃气轮机; 不支持 RemoveRange() 违背 列表<&燃气轮机; . 这是从列表切换到ObservableCollection时可能需要进行的调整的一部分。

        3
  •  6
  •   kotodev Alfred B. Thordarson    6 年前

    我可能和你有类似的问题,但我不确定。

    我有一个 ObservableCollection<MyEntity> ListBox 一定会的。但对一些人来说 我的 列表框 MyEntity 列表中的对象。

    http://www.wblum.org/listbind/net3/index.html

    这是一个非常好的描述,你必须做什么才能得到一个好的结果 当列表或其中的对象更改时更新。希望你能从中受益。

        4
  •  4
  •   Timothy Khouri    16 年前

    我昨天也有同样的问题,这完全是一堆废话:)。。。不过,我不会再将我的设置为空。在我的场景中,我将其设置为MyList.ToArray()(每次添加到列表后)。

    我看到了多个“哦,你需要使用可观察列表”<-一派胡言。

    请原谅我的心烦意乱,但我也希望这能奏效:)

        5
  •  3
  •   Berger    5 年前

    我知道它已经有点老了,但今天我面临着同样的问题。我更新了ObservableCollection中对象的一个属性,视图没有更新,但后来我发现 this 很棒的文章。

    我认为手动触发ObservableCollection的更新是一个非常干净的解决方案:

    CollectionViewSource.GetDefaultView(this.myObservableCollection).Refresh();
    
        6
  •  2
  •   KP.    15 年前

    这是旧的东西,但是,使用可观察的集合。如果希望UI看到ObservableCollection对象中属性的更新,则需要在该对象的类Defention中实现INotifyPropertyChanged。然后在每个属性的setter中引发属性更改事件。

    Public Class Session
    Implements INotifyPropertyChanged
    
    Public Event PropertyChanged As PropertyChangedEventHandler _
       Implements INotifyPropertyChanged.PropertyChanged
    
    Private Sub NotifyPropertyChanged(ByVal info As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
    End Sub
    
    Private _name As String = "No name"
    ''' <summary>
    ''' Name of Session
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
            NotifyPropertyChanged("Name")
        End Set
    End Property
    
        7
  •  0
  •   Peter Peter    16 年前

    如果您有一个对象的ObservableList,并且您正在更改这些对象内部的属性,则通知不适用,因为集合没有直接更改。在更改对象属性后,我使用Insert()将更改后的对象重新添加到集合中,然后使用RemoveAt()删除旧副本,从而强制执行通知。虽然不漂亮,但它很管用。

        8
  •  0
  •   flobadob    10 年前

    在我看来,它更像是ListBox和ListView中的一个bug。我绑定到一个ObservableCollection,集合中的项实现INotifyPropertyChanged。当我动态按下“添加项目”按钮时,UI不显示添加的项目,但是我有一个绑定到MyCollection.Count的计数器控件。每次按下“添加项目”按钮时,此计数器控件都会递增。如果调整视图的大小,列表框将显示我添加的所有项目。因此,ListBox控件上的ItemSource绑定被破坏。我还注意不要在任何时候创建新的MyCollection,这会破坏绑定。呜呜。