【问题标题】:How do I notify changes for a bound property that wholly depends on an ObservableCollection?如何通知完全依赖于 ObservableCollection 的绑定属性的更改?
【发布时间】:2013-03-22 01:55:14
【问题描述】:

我有一个类的绑定属性,Foo,其定义类似于如下(为清楚起见进行了编辑),

public class Foo : INotifyPropertyChanged
{
    public Foo()
    {
        // This should notify when IsHidden changes?
        MyApp.ViewModel.HiddenCategories.CollectionChanged += (s, e) => {
            this.NotifyPropertyChanged("IsHidden");
        };
    }

    public CategoryId Category { get; set; }

    // IsHidden depends on a `global' ObservableCollection object on the ViewModel
    public bool IsHidden 
    {
        get { return MyApp.ViewModel.HiddenCategories.Contains(this.Category); }
    }
    // IsHidden is toggled by adjusting the global ObservableCollection - how to notify the UI? 
    public void ToggleHidden()
    {
        if (this.IsHidden)
            MyApp.ViewModel.HiddenCategories.Remove(this.Category);
        else
            MyApp.ViewModel.HiddenCategories.Add(this.Category);
    }

    #region INotifyPropertyChanged members
    ...

}

ViewModel 上定义了以下内容,

public class FooRegion
{
    public string RegionName { get; set; }
    // Foos is bound in the top ListBox DataTemplate 
    // Each Foo has properties bound in the sub ListBox DataTemplate
    public ObservableCollection<Foo> Foos { get; set; }
}

// This is actually what is bound to the top level ListBox
public ObservableCollection<FooRegion> FoosByRegion { get; set; }

public ObservableCollection<CategoryId> HiddenCategories { get; set; }

我的XAML在资源中定义了两个ItemTemplates如下,

<phone:PhoneApplicationPage.Resources>
...
<DataTemplate x:Key="MainItemTemplate">
    <StackPanel >
        <TextBlock Text="{Binding Name}"/>
        <ListBox ItemsSource="{Binding Foos}"  
            ItemTemplate="{StaticResource SubItemTemplate}" />
    </StackPanel>
</DataTemplate>
... 
<DataTemplate x:Key="SubItemTemplate">
    <StackPanel  Opacity="{Binding IsHidden, Converter={StaticResource BoolToOpacity}}" >
        <toolkit:ContextMenuService.ContextMenu>
            <toolkit:ContextMenu>
                <toolkit:MenuItem Header="{Binding IsHidden, ConverterParameter=unhide foo|hide foo, 
                    Converter={StaticResource BoolToStrings}}" Tap="toggleHideFooContextMenuItem_Tap" />
            </toolkit:ContextMenu>
        </toolkit:ContextMenuService.ContextMenu>
        <TextBlock Text="Some Text Here"/>
    </StackPanel>
</DataTemplate>
...
</phone:PhoneApplicationPage.Resources>

这些资源被调用到一个“嵌套”列表框,如下所示,

<ListBox ItemTemplate="{StaticResource MainItemTemplate}" ItemsSource="{Binding FoosByRegion}" />

此方法似乎只是零碎工作,一些 Foo 对象在 UI 中更新,但其他对象没有 - 好像通知没有到达 UI。

我应该如何解决这个问题?

【问题讨论】:

  • 我认为问题不在于“竞赛” - 您是否调试以查看它的去向/时间(只需设置断点,您应该会看到它)。我认为你更有可能是例如在某处“重置”集合 - 并且不重新连接事件(您应该同时执行 -= +=) - 或者不触发 GUI 更改回集合(尽管不太可能发生)。这取决于您如何更改收藏。此外,该事件只能检测“添加”、删除的项目 - 而不是个别更改 - 请参阅此 link
  • GUI 在Foo 上调用ToggleHidden() 方法,该方法从MyViewModel.HiddenCategories 添加或删除this.Category(实际上是一个枚举)。我对在枚举对象上触发事件不感兴趣,只是在删除或添加项目时触发。调试似乎很有意义,现在看来 IsHidden 没有在 UI 中更新...
  • 让 IsHidden 也有一个“二传手”。也许你有一些通往 Foo.IsHidden 的“复合”路径——或者是这样。如果您发布更多代码/XAML,我明天会看看,干杯。
  • 我已经包含了更多细节 - 也许重要的是我有一个 ObservableCollection 的对象,每个对象都包含一个 ObservableCollection ...
  • 'this.NotifyPropertyChanged("IsHidden");'尝试将其直接移动到ToggleHidden - 并检查您是否曾经调用过该切换方法(调试) - 以及它是否正确添加/删除了它。还要在 IsHidden 'getter' 上休息一下,看看在你通知 'someone' 之后是否真的在里面。这可能是你“初始化”集合的方式(如果是层次结构,甚至更多)——只有一次,或者如果你曾经“取消”并重新创建——那么你将丢失事件。你有一个“不幸”的 MVVM——你正在为那个列表调用“up”——我会将“隐藏”作为类别的一部分(复杂)——而不是添加/删除——而是根据标志隐藏 cat

标签: c# windows-phone-7 binding asynchronous


【解决方案1】:

Windows Phone Toolkit 中的ContextMenu 应用了一个影响周围元素不透明度的动画。将不透明度单独应用于子元素解决了这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 2018-01-23
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 2018-09-20
    相关资源
    最近更新 更多