2

そのため、コードを再利用できるように、いくつかの DependencyProperties を使用して UserControl を作成しようとしています。ただし、一部のプロパティは更新されていませんが、他のプロパティは更新されています。さらに奇妙なのは、更新されているプロパティに対しても、メソッド「set」がまったく呼び出されていないことです。

これが私のコードです:

ViewModel で:

public ICommand TestCommand = new DelegateCommand(x => MessageBox.Show("Ocorreu Evento"));
public List<string> TestList = new List<string> { "Hello","This","is","a","Test" };

ビューで:

<views:CustomizedList Header="Testing"
                        Items="{Binding TestList}"/>

ユーザー コントロール ビュー:

<StackPanel>
    <Label Content="{Binding Header}" />
    <ListBox ItemsSource="{Binding Items}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="Hello"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

ユーザー制御コード:

    public string Header
    {
        get { return (string)GetValue(HeaderProperty); }
        set
        {
            MessageBox.Show("New header is " + value); 
            SetValue(HeaderProperty, value);
        }
    }       

    public BindingList<object> Items
    {
        get { return (BindingList<object>)GetValue(ItemsProperty); }
        set {
            SetValue(ItemsProperty, value);
            Console.WriteLine("Value was set with " + value.Count + " items.");
        }
    }

    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register("Header", typeof(string),
          typeof(ListaCustomizada));

    public static readonly DependencyProperty ItemsProperty =
        DependencyProperty.Register("Items", typeof(BindingList<object>),
          typeof(ListaCustomizada));

ヘッダーは表示されていますが、アイテムは表示されていません。メソッドが呼び出されているかどうかを確認するためにコンソール出力を追加したわけではありませんが、ヘッダーであっても何も表示されません。UserControl の DataContext をそれ自体に設定しています。

何か案は?

編集:

@Garry Vass の提案に従って、Callback 関数を追加しました。新しいコードは次のとおりです。

    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register("Header", typeof(string),
          typeof(ListaCustomizada), new PropertyMetadata("", ChangedCallback));

    public static readonly DependencyProperty ItemsProperty =
        DependencyProperty.Register("Items", typeof(BindingList<object>),
          typeof(ListaCustomizada), new PropertyMetadata(new BindingList<object>(), ChangedCallback));

    private static void ChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Console.WriteLine("Dependency property is now " + e.NewValue);
    }

これで、Header の値が変化していることがわかりますが、Items に対するコールバックは発生していません。

編集:

TestList をフィールドではなくプロパティに変更し、そのタイプを BindingList に変更して、ユーザー コントロール内のデータと一貫性を持たせましたが、結果は同じです。

    public BindingList<object> TestList { get; set; }

    public ViewModel()
    {
        TestList = new BindingList<object> { "Hello", "This", "is", "a", "Test" };
    }

編集: さらにテストすると、ユーザーコントロール上のDPがVMにバインドされているビューのDPにバインドされているという事実からエラーが発生することがわかりました。

編集: ついに機能しました。もう少し深く検索すると、ユーザーコントロールの作成方法を完全に説明するこのリンクが codeproject に見つかりました。

4

1 に答える 1

2

直感に反するように思えるかもしれませんが、WPF バインディング エンジンは基本的にコード内のセッターとゲッターを無視し、WPF 配管の奥深くにある独自のバージョンを使用します。したがって、介入するために、またはあなたの場合は検査するためにそこに置いたコードは、実行されないままになります。

では、なぜ彼らはそこにいるのでしょうか。これらはコンパイル時のヘルパーであり、Xaml に接続するものを提供します。

依存関係プロパティに介入したり、何が起こっているかを調べたりしたい場合は、次のように宣言できます...

    #region MyProperty (DependencyProperty)
    public int MyProperty
    {
        get { return (int)GetValue(MyPropertyProperty); }
        set { SetValue(MyPropertyProperty, value); }
    }
    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int), typeof(MainWindow),
          new PropertyMetadata(0, ChangedCallback));
    private static void ChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Console.WriteLine("Dependency property is now " + e.NewValue);
    }
    #endregion

これは、Property Changed コールバックを使用して Dependency Property を宣言します。WPF は、プロパティが設定されるたびにそれを呼び出します。

Console ステートメントがある場所にデバッガーを固定することで、コールバック メソッドで発生する変更を確認できます。

于 2013-08-02T17:40:46.060 に答える