5

依存関係のプロパティについて多くの投稿があったことを知っているので、私は精査し、精査しましたが、うまくいく解決策を持っているものを見たことがありません。ViewModelからAutoCompleteBoxにObservableCollectionをバインドしようとしています。私のViewModelがデータを返し、ゲッターがヒットしています。ただし、その後、コントロールの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のStringDependencyPropertyを作成しました。SearchTextをバインドすると、正常に機能します。OnSearchTextPropertyChangedは次のように呼び出されます。

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

他の誰かがWinRTでこれらの問題を経験していますか?または、私がしていることに何か問題がありますか?

4

3 に答える 3

5

2つの簡単な解決策があります

(ここで、 BaseClassは、たとえば、派生元の抽象クラスまたはインターフェイスであり、依存関係プロパティにバインドしようとしているインスタンスです)

Solution 1:

You need to change typeof(BaseClass) to typeof(object) when registering a dependency property. Getter and setter may continue use your BaseClass, but be aware of InvalidCastException if you set a different type instance to this dependency property.

        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));

Solution 2:

Create a dummy dependency property somewhere in your code (for example right after the dependency property you are trying to create) that will have a type of all your derived types. Like this:

#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

Here DerivedClass1 is derived from BaseClass.

Why?

I suppose the reason is that XAML doesn't know anything about your derived types and only knows about the BaseClass. So creating a dummy dependency property for each type should solve the problem.

于 2014-09-24T18:02:52.903 に答える
2

バインディングがDebugConverterで起動するかどうかを確認してみます-WinRTXAMLToolkitBindingDebugConverterを確認します-バインディングのコンバーターとして設定し、それが壊れるかどうか、いつ壊れるかを確認します(ConvertまたはConvertBackのどちらで、どの値が設定されていますか)等。)。

それでも問題が解決しない場合は、DataContextが正しく設定されているかどうかを確認してください。

*編集1

探しているのがバインドされたコレクションのアイテムの変更である場合(ItemsSourceがINotifyCollectionChangedであるかどうかを確認でき、trueの場合)、 CollectionChangedイベントをサブスクライブして変更を確認できます。それ以外の場合は、 ItemsControlから継承し、 GetContainerForItemOverrideIsItemItsOwnContainerOverrideなどのメソッドをオーバーライドするようにコントロールを変更できます。

*編集2

依存関係プロパティのタイプとしてIEnumerableを使用することに関連して、Windows 8ConsumerPreviewのフレームワークにバグがあるようです。タイプとしてオブジェクトを使用すると、問題が解決します。ネイティブコードのデバッグを有効にすると、次のバインディング例外が表示されます。

エラー:コンバーターはタイプ'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'; ターゲット要素は'ACBDP.AutoCompleteBox'(Name ='null'); ターゲットプロパティは「ItemsSource」(タイプ「IEnumerable」)です。

于 2012-05-11T06:30:32.527 に答える
0

typeof(IEnumerable)をtypeof(object)に変更します

于 2012-10-11T12:46:54.783 に答える