【发布时间】: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