【问题标题】:DepencyProperty not being update from binding on UserControlDepencyProperty 未从 UserControl 上的绑定更新
【发布时间】:2013-08-02 16:10:27
【问题描述】:

所以,我正在尝试使用一些 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 的建议,我添加了一个回调函数。新代码是:

    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绑定到视图上的DP,该DP绑定到VM。

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

【问题讨论】:

  • WPF 中的 DependencyProperties 是一种特殊的属性。话虽如此,您的Console.WriteLine()MessageBox.Show() 很可能是原因。 DependencyProperties 除了原来的 getter 和 setter 之外,不应该有任何额外的东西。
  • 好吧,我在注意到没有任何变化后添加了它们,因此它们不是根本原因。我删除了它们并得到了相同的症状:标题值正在显示,但集合没有。从外观上看,它应该是双重绑定(ViewModel->View->UserControl)

标签: c# wpf data-binding user-controls dependency-properties


【解决方案1】:

虽然看起来违反直觉,但 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 语句所在的位置,您将看到回调方法中发生的变化。

【讨论】:

  • 我试过了。它适用于 Header(我可以看到值已更改),但我怀疑 Items 属性的回调根本没有被调用。
  • 您的“TestList”必须是具有公共 getter 和 setter 的属性。您正在将其初始化为一个字段。创建一个属性并在 VM 的构造函数中对其进行初始化。此外,人们喜欢使用 ObservableCollection 而不是 List,但如果要绑定,它仍然必须是 PROPERTY
  • 为TestList添加了一个{get;set;},将类型更改为BindingList,仍然得到相同的结果。
  • 我现在看到了。这与您的虚拟机有关!主窗口的 DC 在哪里设置?
  • 我相信VM也可以。我只是复制和粘贴重要的部分,但是在我将视图(这是一个用户控件)的数据上下文设置到 VM 之后不久。所有绑定都在 VM/V 之间工作,问题在于跳转 VM->V->UC
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 2011-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-21
相关资源
最近更新 更多