web-dev-qa-db-ja.com

「バインディング」は、DependencyObjectのDependencyPropertyでのみ設定できます

TextBoxに基づくカスタムコントロールから、次のようにItemsという名前のプロパティを作成しました。

public class NewTextBox : TextBox
{
    public ItemCollection Items { get; set; }
}

XAMLでカスタムコントロールを使用する場合、「 'Binding'はDependencyObjectのDependencyPropertyでのみ設定できます」という例外が発生するため、プロパティをバインドできません。

この例外を解決するにはどうすればよいですか?

45
mgottschild

補足として、オブジェクト間でコピーして貼り付け、2番目のtypeof(Object)ステートメントの変更を忘れると、これらのバインディングエラーが発生することに注意してください。

すべてが定義されていて正しいように見えたので、なぜこのエラーが発生していたのか、私はかなりの時間把握できませんでした。単一のセットからリストに移動したいので、プロパティをユーザーコントロールに移動しました。したがって:

public static readonly DependencyProperty FoldersProperty = DependencyProperty.Register("Folders", typeof(OutlookFolders), typeof(MainWindow), new FrameworkPropertyMetadata(new OutlookFolders()));

public OutlookFolders Folders
{
    get { return GetValue(FoldersProperty) as OutlookFolders; }
    set { SetValue(FoldersProperty, value); }
}

次のようになっているはずです。

public static readonly DependencyProperty FoldersProperty = DependencyProperty.Register("Folders", typeof(OutlookFolders), typeof(SavedFolderControl), new FrameworkPropertyMetadata(new OutlookFolders()));

public OutlookFolders Folders
{
    get { return GetValue(FoldersProperty) as OutlookFolders; }
    set { SetValue(FoldersProperty, value); }
}

この変更を行うまで、エラーを受け取り続けました:A 'Binding' cannot be set on the property 'Folders' of type 'SavedFolderControl'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

76
netniV

この例外を解決するには、プロパティItemsを変更し、XAMLで「リンク」として機能するDependencyPropertyを追加する必要があります。クラスは次のとおりです。

public class AutocompleteTextBox : TextBox
{
    public ItemCollection Items
    {
        get {
            return (ItemCollection)GetValue(ItemsProperty); }
        set {
            SetValue(ItemsProperty, value); }
    }

    public static readonly DependencyProperty ItemsProperty =
        DependencyProperty.Register(
            "Items",
            typeof(ItemCollection),
            typeof(AutocompleteTextBox),
            new PropertyMetadata(default(ItemCollection), OnItemsPropertyChanged));

    private static void OnItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // AutocompleteTextBox source = d as AutocompleteTextBox;
        // Do something...
    }
27
mgottschild

別の落とし穴があります:DependencyProperty.Register()の最初の引数の文字列が関連するプロパティの名前と一致することを確認してください。

public static readonly DependencyProperty ItemsProperty =
    DependencyProperty.Register(
        "TheItems", // This is wrong
        typeof(ItemCollection),
        typeof(AutocompleteTextBox),
        new PropertyMetadata(default(ItemCollection), OnItemsPropertyChanged));

文字列を変更せずにプロパティの名前を変更すると、この問題が発生しました。

22
Oliver

これの別の潜在的な原因は、メタデータのデフォルト値に不正なタイプを指定した場合です。
例えば:

new PropertyMetadata(default(ItemCollection), OnItemsPropertyChanged)

あなたが代わりに書いた場合、このエラーがスローされます:

new PropertyMetadata(false, OnItemsPropertyChanged)

これは、コードソースからコピーして貼り付ける場合にも発生する可能性があります。

(ランタイム+デザインタイム)メッセージがありました:

PresentationFramework.dllで「System.Windows.Markup.XamlParseException」タイプの未処理の例外が発生しました

追加情報:タイプ「トリガー」の「プロパティー」プロパティーに「バインディング」を設定できません。 「バインディング」は、DependencyObjectのDependencyPropertyでのみ設定できます。

VMプロパティでトリガーを定義するのに十分賢いところです。

// incorrect.. cannot have Trigger for VM property
<Trigger Property="{Binding IsExpanded}" Value="True">
  <Setter Property="Visibility" Value="Visible"/>
</Trigger>

もちろん、これはデータトリガーである必要があります(プロパティの代わりにバインディングを使用します)

<DataTrigger Binding="{Binding IsExpanded}" Value="True">
  <Setter Property="Visibility" Value="Visible"/>
</DataTrigger>

トリガーは通常、コントロール(Button、TextBox、FrameworkElementなど)のプロパティ用です。

1
EricG