2

所以,我试图用一些 DependencyProperties 创建一个 UserControl,以便我可以重用代码。但是,有些属性没有更新,而另一些属性正在更新。更奇怪的是,即使对于那些正在更新的属性,方法“set”也根本没有被调用。

这是我的代码:

在视图模型上:

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 建议之后,我添加了一个回调函数。新代码是:

    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 ont eh 用户控件绑定到视图上的 DP,该视图绑定到 VM。

编辑: 终于让它工作了。搜索得更深一点,我在 codeproject 上找到了这个链接,它完美地解释了如何创建用户控件。

4

1 回答 1

2

虽然它可能看起来违反直觉,但 WPF 绑定引擎基本上会忽略代码中的 setter 和 getter,并使用其自己的版本,该版本位于 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 回调的依赖属性。每当设置属性时,WPF 都会调用它。

通过将调试器锚定在 Console 语句所在的位置,您将看到回调方法中发生的变化。

于 2013-08-02T17:40:46.060 回答