" ListenerOffset"属性已经由" UserControl"注册

时间:2017-08-29 04:12:18

标签: c# wpf

我想实现"滚动以加载更多"功能。附加自定义绑定以检查ScrollViewer verticalOffset属性是否已更改。以下代码用于在ListBox加载上注册绑定。

public static ScrollViewer scrollViewer;
public static DependencyProperty offsetChangeListener;
public static Binding binding;

private void initScrollViewerMonitor(object sender, RoutedEventArgs e)
{
    //get the ScrollViewer from the ListBox
    scrollViewer = GetDescendantByType(accountHistoryList, typeof(ScrollViewer)) as ScrollViewer;


    //attach to custom binding to check if ScrollViewer verticalOffset property has changed
    if (binding == null || offsetChangeListener == null)
    {
        var binding = new Binding("VerticalOffset") { Source = scrollViewer };
        offsetChangeListener = DependencyProperty.RegisterAttached(
                                "ListenerOffset",
                                typeof(object),
                                typeof(UserControl),
                                new PropertyMetadata(OnScrollChanged));
        scrollViewer.SetBinding(offsetChangeListener, binding);
    }
}

但是当第二次重新加载ListBox时,会出现以下错误。

  

System.ArgumentException:'' ListenerOffset'财产已经   由" UserControl"。'

注册

我可以在卸载时取消注册吗?

2 个答案:

答案 0 :(得分:-1)

发生了什么是依赖属性在同一名称和所有者下多次注册。依赖属性旨在拥有单个所有者,并且应该静态实例化。如果您没有静态实例化它们,则会尝试为每个控件实例注册它们。

将DependencyProperty声明设置为静态(不在函数内部)

public static DependencyProperty offsetChangeListener = DependencyProperty.RegisterAttached(
                                "ListenerOffset",
                                typeof(object),
                                typeof(UserControl),
                                new PropertyMetadata(OnScrollChanged));

同时检查" typeof(UserControl)"应该是实际控件而不是它的基类.RegisterAttached(ownerType)的第三个参数必须始终是声明属性的类。

答案 1 :(得分:-1)

依赖属性应该静态分配,不应该基于实例。例外情况是告诉您该属性已经由UserControl类型注册。

  

应该用于设置值的依赖项属性标识符   在您的班级中公共静态只读字段。那个标识符是   然后用于引用依赖属性以用于操作   例如以编程方式设置其值或获取元数据。   MSDN

现在,我可以看到您正在检查附加的媒体资源,但是您正在查看if(binding == null) { ... },但是您正在定义var binding更低版本。 var ..正在创建一个新变量binding而不使用您的类变量binding。因此var binding is not equal to binding ...这可能与您的实例无关。

现在基本上你要做的就是创建你的offsetChangeListener static readonly 属性,例如。

static readonly DependencyProperty offsetChangeListener = DependencyProperty.RegisterAttached("ListenerOffset",
                                                                                                typeof(object),
                                                                                                typeof(UserControl),
                                                                                                new PropertyMetadata(OnScrollChanged));

现在你需要跟踪你已经注册了绑定,但是如果你只在init阶段注册(即构造函数等),你可以确定你只注册了一次。

private void initScrollViewerMonitor(object sender, RoutedEventArgs e)
{
    var binding = new Binding("VerticalOffset") { Source = scrollViewer };
    scrollViewer.SetBinding(offsetChangeListener, binding);
}