列表绑定源更改后不显示集合元素行为状态

发布于 2024-12-02 05:20:03 字数 2317 浏览 1 评论 0原文

我是 WPF 新手,最近遇到了一个问题。我有一个 ObservableCollection<坦克车>我的 ViewModel 中的 TankCars 是视图中列表框的绑定源。 ListBox 具有 ItemTemplate,它定义了两种行为:

<i:Interaction.Behaviors>
    <ei:DataStateBehavior x:Name="Type62DataStateBehavior" Binding="{Binding Type}" Value="62" TrueState="IsType62"/>
    <ei:DataStateBehavior x:Name="Type66DataStateBehavior" Binding="{Binding Type}" Value="66" TrueState="IsType66"/>
</i:Interaction.Behaviors>

当我将项目添加到集合中时,我可以看到它们出现在列表中。但直到我调用 TankCars[i].RaisePropertyChanged("Type")
后才会显示状态 此外,当我需要切换到另一个集合时,我调用代码:

TankCars = new ObservableCollection<TankCar> (GetTankCars());
RaisePropertyChanged("TankCars"); //to notify the ListBox
foreach (var car in TankCars) {car.RaisePropertyChanged("Type");} //make states change (not working)

并且似乎在我通过引发 TankCars 属性更改事件更改 ItemSource 绑定后,不会显示项目状态(TankCar PropertyChangedEvent 目前未绑定到任何内容)。如果我在表单上放置一个按钮,该按钮将启动为项目调用 car.RaisePropertyChanged("Type") 的命令,它会刷新项目状态。

所以问题是:如何正确处理,以便在将新项目添加到集合中以及将其替换为另一个项目后触发项目的行为?当我在更改 ListBox 项目源之后引发 PropertyChanged 时,为什么项目状态没有刷新?

更新:使用下面的代码解决了(也有助于这个答案< /a>)。不再需要手动为收藏项提高 PropertyChanged,我很高兴:)

public class SmartDataStateBehavior : DataStateBehavior
{
    protected override void OnAttached()
    {
        base.OnAttached();

        if (AssociatedObject != null)
        {
            AssociatedObject.Loaded += AssociatedObjectLoaded;
        }
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        if (AssociatedObject != null)
        {
            AssociatedObject.Loaded -= AssociatedObjectLoaded;
        }
    }

    private void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
    {
        if (Binding == null || Value == null) return;

        if (Binding.ToString() == Value.ToString())
        {
            if (TrueState != null)
                VisualStateManager.GoToElementState(AssociatedObject, TrueState, true);
        }
        else
        {
            if (FalseState != null)
                VisualStateManager.GoToElementState(AssociatedObject, FalseState, true);
        }
    }

}

I'm quite new at WPF and recently encountered a problem. I got an ObservableCollection< TankCar> TankCars in my ViewModel which is the Binding Source for a ListBox in the view. The ListBox has ItemTemplate that defines two behaviors:

<i:Interaction.Behaviors>
    <ei:DataStateBehavior x:Name="Type62DataStateBehavior" Binding="{Binding Type}" Value="62" TrueState="IsType62"/>
    <ei:DataStateBehavior x:Name="Type66DataStateBehavior" Binding="{Binding Type}" Value="66" TrueState="IsType66"/>
</i:Interaction.Behaviors>

When I add items to the collection, I can see them appear in the list. But the state is not shown until I call TankCars[i].RaisePropertyChanged("Type")
Moreover, when I need to switch to another collection, I call the code:

TankCars = new ObservableCollection<TankCar> (GetTankCars());
RaisePropertyChanged("TankCars"); //to notify the ListBox
foreach (var car in TankCars) {car.RaisePropertyChanged("Type");} //make states change (not working)

and it appears that after I change ItemSource binding through raising TankCars property change event, items states are not shown (TankCar PropertyChangedEvent is not bound to anything at the moment). If I place a button on a form, that launches the command that calls car.RaisePropertyChanged("Type") for the items, it refreshes the items states.

So the question is: how to make things right to make the behavior of the items trigger after adding new items to a collection and after replacing it by another one? And why the items states are not refreshed, when I raise PropertyChanged just after the changing ListBox item source?

Update: solved with the code below (also helped this answer). And no more manual raising PropertyChanged for collection items, I'm happy :)

public class SmartDataStateBehavior : DataStateBehavior
{
    protected override void OnAttached()
    {
        base.OnAttached();

        if (AssociatedObject != null)
        {
            AssociatedObject.Loaded += AssociatedObjectLoaded;
        }
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        if (AssociatedObject != null)
        {
            AssociatedObject.Loaded -= AssociatedObjectLoaded;
        }
    }

    private void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
    {
        if (Binding == null || Value == null) return;

        if (Binding.ToString() == Value.ToString())
        {
            if (TrueState != null)
                VisualStateManager.GoToElementState(AssociatedObject, TrueState, true);
        }
        else
        {
            if (FalseState != null)
                VisualStateManager.GoToElementState(AssociatedObject, FalseState, true);
        }
    }

}

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

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

发布评论

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

评论(1

蓝天 2024-12-09 05:20:03

当您刚刚添加项目时,尚未创建相应的容器及其行为,因此类型尚未绑定,从而使通知毫无意义。

您通常不需要在属性的设置器之外发出通知,因此我会尽量避免手动执行所有这些操作。

我不知道你的行为会做什么,但如果它以某种方式影响类型,你应该将该通知逻辑放入类型的设置器中(如果它有一个)或放入行为的 OnAttached 重写方法中。

When you have just added the items the respective containers with their behaviours have not yet been created and hence the type is not bound yet, making the notification meaningless.

You normally should not need to raise notifications outside the setter of a property, so i would try to avoid doing all that manually.

I do not know what your behavior does but if it affects the type somehow you should put that notification logic either into the setter of type if it has one or into the OnAttached override method of the bahaviour.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文