WinRT DependencyProperty,IEnumerable完全没有触发

时间:2012-05-11 01:01:00

标签: dependency-properties windows-runtime

我已经仔细搜索过了,因为我知道有很多关于依赖属性的内容,但我还没有看到任何有效的解决方案。我正在尝试将ObservableCollection从我的ViewModel绑定到我的AutoCompleteBox。我的ViewModel正在返回数据,Getter正在被击中。但是,之后,控件的SetValue或OnItemsSourcePropertyChanged不会触发。有什么可能是错的想法吗?

我有一个像这样的控件:

[ContentProperty(Name = "ItemsSource")]
public partial class AutoCompleteBox : Control
{
    //local stuff
    private ListBox lb;
    private List<Person> _items;
    private ObservableCollection<Person> _view;

    public AutoCompleteBox() : base()
    {
        DefaultStyleKey = typeof(AutoCompleteBox);
        Loaded += (sender, e) => ApplyTemplate();
    }
    protected override void OnApplyTemplate()
    {
        this.lb = this.GetTemplateChild("Selector") as ListBox;
        base.OnApplyTemplate();

    }
    #region ItemsSource

    public IEnumerable ItemsSource
    {
        get { return GetValue(ItemsSourceProperty) as ObservableCollection<Person>; }
        set { SetValue(ItemsSourceProperty, value); } //Never gets called
    }

    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register(
            "ItemsSource",
            typeof(IEnumerable),
            typeof(AutoCompleteBox),
            new PropertyMetadata(null, OnItemsSourcePropertyChanged));

    private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
       //Never gets called :(
    }
    #endregion

    public String SearchText
    {
        get { return GetValue(SearchTextProperty) as String; }
        set
        {
            SetValue(SearchTextProperty, value);
        }
    }


    public static readonly DependencyProperty SearchTextProperty =
        DependencyProperty.Register(
            "SearchText",
            typeof(String),
            typeof(AutoCompleteBox),
            new PropertyMetadata(null, OnSearchTextPropertyChanged));

    private static void OnSearchTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
         //gets fired when loaded, with data being bound
    }

}

以下是如何使用控件:

<toolkit:AutoCompleteBox Grid.Row="5" Grid.Column="2" ItemsSource="{Binding Persons,Mode=TwoWay}" SearchText="WhatTheHell"/>

作为测试并且为了简单起见,我为SearchText创建了一个String DependencyProperty。如果我绑定SearchText,它会正常工作,调用OnSearchTextPropertyChanged:

<toolkit:AutoCompleteBox Grid.Row="5" Grid.Column="2" ItemsSource="{Binding Persons,Mode=TwoWay}" SearchText="{Binding SearchText}"/>

其他人是否遇到过WinRT的这些问题?或者看到我在做什么有什么问题?

3 个答案:

答案 0 :(得分:5)

有2种快速解决方案

(这里 BaseClass 例如是一个抽象类或您从中派生的接口以及您尝试绑定到依赖项属性的实例)

解决方案1:

注册依赖项属性时,需要将typeof(BaseClass)更改为typeof(object)。 Getter和setter可以继续使用 BaseClass ,但如果为此依赖项属性设置了不同的类型实例,请注意InvalidCastException。

        public BaseClass Item
        {
            get { return (BaseClass)GetValue(ItemProperty); }
            set { SetValue(ItemProperty, value); }
        }
        public static readonly DependencyProperty ItemProperty =
            DependencyProperty.Register("Item", typeof(object), typeof(MyUserControl), new PropertyMetadata(null));

解决方案2:

在代码中的某处创建一个虚拟依赖项属性(例如,在您尝试创建的依赖项属性之后),它将具有所有派生类型的类型。 像这样:

#region DummyProperty

public DerivedClass1 Dummy
{
    get { return (DerivedClass1)GetValue(DummyProperty); }
    set { SetValue(DummyProperty, value); }
}

public static readonly DependencyProperty DummyProperty =
    DependencyProperty.Register("Dummy", typeof(DerivedClass1), typeof(MyUserControl), new PropertyMetadata(default(DerivedClass1)));

#endregion

此处 DerivedClass1 源自 BaseClass

为什么?

我认为原因是XAML对您的派生类型一无所知,只了解 BaseClass 。因此,为每种类型创建虚拟依赖项属性应该可以解决问题。

答案 1 :(得分:2)

我会尝试检查绑定是否会使用DebugConverter触发 - 检查BindingDebugConverter中的WinRT XAML Toolkit - 将其设置为绑定的转换器,并查看它是否以及何时中断(是否在转换或ConvertBack,正在设置什么值等。)。

如果这没有帮助 - 请检查您的DataContext是否设置正确。

*编辑1

如果您要查看的是绑定集合的项目中的更改 - 您可以检查ItemsSource是否为INotifyCollectionChanged,如果为true,则订阅CollectionChanged事件以查看更改。否则 - 您可以修改您的控件以继承ItemsControl并覆盖GetContainerForItemOverrideIsItemItsOwnContainerOverride等方法。

*编辑2

似乎在Windows 8 Consumer Preview的框架中有a bug与使用IEnumerable作为依赖项属性的类型相关。使用object作为类型可以解决问题。如果启用本机代码调试,您将看到此绑定异常:

  

错误:转换器无法转换类型'System.Collections.ObjectModel.ObservableCollection`1 [[ACBDP.Person,ACBDP,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]],System,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089'键入'IEnumerable'; BindingExpression:Path ='Persons'DataItem ='ACBDP.BlankPageViewModel,ACBDP,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'; target元素是'ACBDP.AutoCompleteBox'(Name ='null'); target属性是'ItemsSource'(输入'IEnumerable')。

答案 2 :(得分:0)

将typeof(IEnumerable)更改为typeof(object)