即使触发 CollectionChanged 或 PropertyChanged 事件,UI 也不会更新

发布于 2024-12-14 08:45:26 字数 2893 浏览 5 评论 0原文

背景,来自MSDN:

ObservableCollections CollectionChanged 事件只会引发 当 ObservableCollection 的属性发生更改时(另外, 删除元素),而当现有元素的属性发生更改时

很糟糕,因为我需要在现有元素的特定属性发生更改时更新 UI。我尝试触发 CollectionChanged 事件和 PropertyChanged 事件,但都不起作用。

我的情况:

在我的应用程序中,我有一个listbox绑定到observablecollection,其中项目的可见性取决于“Favorite”属性每个项目都使用 BoolToVisibilityConverter。 XAML:

                <ListBox x:Name="FavoritesListBox"
                     Margin="0,0,-12,0"
                     ItemsSource="{Binding FeedItemOCollection}"
                     SelectionChanged="FavoritesListBox_SelectionChanged">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Name="FavoritesStackPanel"
                                    Margin="0,0,0,17" Visibility="{Binding Favorite, Converter={StaticResource BooltoVisibilityConverter}}">
                            <TextBlock Text="{Binding Title}"
                                       TextWrapping="Wrap"
                                       Margin="12,0,0,0"
                                       Style="{StaticResource PhoneTextLargeStyle}" />
                            <TextBlock Text="{Binding PublishDate,Converter={StaticResource DateTimeToDateConverter}}"
                                       TextWrapping="Wrap"
                                       Margin="12,-6,12,0"
                                       Style="{StaticResource PhoneTextSmallStyle}" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

注意:该对象在 App.Xaml.cs 中初始化,因此对于整个应用程序来说是全局的。这可能是导致事情对我不起作用的不寻常的事情。

一旦发生初始绑定,对元素的收藏夹属性值的更改不会导致该项目在收藏夹列表框中显示或消失,如下所示出于帖子开头所述的原因而需要。这是预料之中的。

为了解决这个问题,我尝试在更改收藏夹属性时触发 CollectionChanged 事件和 PropertyChanged 事件以更新 UI,但都不起作用,我很困惑为什么不呢。我通过在 ObservableCollection 中添加和删除元素成功解决了我的问题,但显然这是一个 hack。代码:

public void MarkFavorite(FeedItem feedItem)
    {
        try
        {
            feedItem.Favorite = true;
            //CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));   <-- why doesn't this work?
            //PropertyChanged(this, new PropertyChangedEventArgs("Count"));  <-- why doesn't this work?
            this.Remove(feedItem);   <-- this works, but is a hack
            this.Add(feedItem);   <-- this works, but is a hack

            SaveToIso();
        }
        catch (Exception exception)
        {
            //TODO: Log this.
        }
    }

为什么触发事件不起作用? 提前非常感谢。

Background, from MSDN:

ObservableCollections CollectionChanged event will only be raised
when properties of ObservableCollection are changed (Addition,
deletion of an element) and not when the properties of existing elements are changed.

Bummer, because I need the UI to update when a specific property of an existing element changes. I tried firing both CollectionChanged events and PropertyChanged Events but neither worked.

My situation:

In my application, I have a listbox bound to an observablecollection where the visibility of the items depends on the "Favorite" property of each item using a BoolToVisibilityConverter. XAML:

                <ListBox x:Name="FavoritesListBox"
                     Margin="0,0,-12,0"
                     ItemsSource="{Binding FeedItemOCollection}"
                     SelectionChanged="FavoritesListBox_SelectionChanged">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Name="FavoritesStackPanel"
                                    Margin="0,0,0,17" Visibility="{Binding Favorite, Converter={StaticResource BooltoVisibilityConverter}}">
                            <TextBlock Text="{Binding Title}"
                                       TextWrapping="Wrap"
                                       Margin="12,0,0,0"
                                       Style="{StaticResource PhoneTextLargeStyle}" />
                            <TextBlock Text="{Binding PublishDate,Converter={StaticResource DateTimeToDateConverter}}"
                                       TextWrapping="Wrap"
                                       Margin="12,-6,12,0"
                                       Style="{StaticResource PhoneTextSmallStyle}" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

Note: This object is initialized in App.Xaml.cs and so is global for the whole application. This may be the unusual thing that is causing things not to work for me.

Once the initial binding occurs, changes to the value of an element's Favorite property does not cause the item to show up or disappear from the Favorites Listbox as is desired for the reason noted at the beginning of the post. This is expected.

To work around this I've tried firing both CollectionChanged events and PropertyChanged Events when the Favorite property is changed to get the UI to update, but neither worked and I'm confused why not. I have succeed in working around my issue, by adding and removing the element from the ObservableCollection, but clearly this is a hack. Code:

public void MarkFavorite(FeedItem feedItem)
    {
        try
        {
            feedItem.Favorite = true;
            //CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));   <-- why doesn't this work?
            //PropertyChanged(this, new PropertyChangedEventArgs("Count"));  <-- why doesn't this work?
            this.Remove(feedItem);   <-- this works, but is a hack
            this.Add(feedItem);   <-- this works, but is a hack

            SaveToIso();
        }
        catch (Exception exception)
        {
            //TODO: Log this.
        }
    }

Why doesn't firing the events work?
Many thanks ahead of time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

咋地 2024-12-21 08:45:26

您的 FeedItem 类必须实现 INotifyPropertyChanged 接口,并且您的 favorite 属性必须如下所示:

私有布尔_Favorite;

private bool _Favorite;
public bool Favorite
{
    get { return _Favorite; }
    set
    {
        _Favorite = value;
        if (PropertyChanged != null)
           PropertyChanged(this, new PropertyChangedEventArgs("Favorite"));
    }
}

或者您可以提取一个方法

private void OnPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

,您的属性将如下所示:

private bool _Favorite;
public bool Favorite
{
    get { return _Favorite; }
    set
    {
        _Favorite = value;
        OnPropertyChanged("Favorite");
    }
}

Your FeedItem class must implement INotifyPropertyChanged interface, and your Favorite property must look like:

private bool _Favorite;

private bool _Favorite;
public bool Favorite
{
    get { return _Favorite; }
    set
    {
        _Favorite = value;
        if (PropertyChanged != null)
           PropertyChanged(this, new PropertyChangedEventArgs("Favorite"));
    }
}

Or you can extract a method

private void OnPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

and your property will look like this:

private bool _Favorite;
public bool Favorite
{
    get { return _Favorite; }
    set
    {
        _Favorite = value;
        OnPropertyChanged("Favorite");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文